-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
258 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
127 changes: 127 additions & 0 deletions
127
apps/client/src/pages/time-table/components/edit-floating-button.css.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import { recipe } from '@vanilla-extract/recipes'; | ||
import { keyframes, style } from '@vanilla-extract/css'; | ||
import { themeVars } from '@confeti/design-system/styles'; | ||
|
||
const fadeInBox = keyframes({ | ||
from: { opacity: 0, transform: 'translateY(80%)' }, | ||
to: { opacity: 1, transform: 'translateY(0)' }, | ||
}); | ||
|
||
const fadeInText = keyframes({ | ||
from: { opacity: 0, transform: 'translateY(20%)' }, | ||
to: { opacity: 1, transform: 'translateY(0)' }, | ||
}); | ||
|
||
const fadeOutText = keyframes({ | ||
from: { opacity: 1, transform: 'translateY(0)' }, | ||
to: { opacity: 0, transform: 'translateY(20%)' }, | ||
}); | ||
|
||
export const box = style({ | ||
padding: '1rem 5.3rem 0.9rem 1.6rem', | ||
bottom: '17rem', | ||
right: '2rem', | ||
|
||
...themeVars.display.flexCenter, | ||
|
||
position: 'absolute', | ||
zIndex: themeVars.zIndex.floatingButton.content, | ||
transition: 'width 0.3s ease-in-out', | ||
...themeVars.fontStyles.subtitle4_b_14, | ||
flexDirection: 'column', | ||
alignItems: 'flex-start', | ||
|
||
borderRadius: '0.5rem', | ||
backgroundColor: themeVars.color.white, | ||
|
||
animation: `${fadeInBox} 0.3s ease-out`, | ||
}); | ||
|
||
export const boxButton = style({ | ||
...themeVars.display.flexCenter, | ||
padding: '0.8rem 0', | ||
cursor: 'pointer', | ||
}); | ||
|
||
export const buttonVariants = recipe({ | ||
base: { | ||
height: '5rem', | ||
position: 'absolute', | ||
right: '2rem', | ||
display: 'flex', | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
borderRadius: '3rem', | ||
backgroundColor: themeVars.color.gray800, | ||
zIndex: themeVars.zIndex.floatingButton.content, | ||
transition: 'width 0.3s ease-in-out', | ||
cursor: 'pointer', | ||
}, | ||
variants: { | ||
variant: { | ||
close: { | ||
bottom: '11rem', | ||
padding: '1.3rem', | ||
width: '5rem', | ||
}, | ||
edit: { | ||
bottom: '11rem', | ||
padding: '0.5rem', | ||
width: '11rem', | ||
}, | ||
complete: { | ||
bottom: '2rem', | ||
padding: '0.5rem', | ||
width: '11rem', | ||
gap: '0.2rem', | ||
}, | ||
}, | ||
}, | ||
defaultVariants: { | ||
variant: 'edit', | ||
}, | ||
}); | ||
|
||
export const text = style({ | ||
...themeVars.fontStyles.subtitle4_b_14, | ||
color: themeVars.color.confeti_lime2, | ||
whiteSpace: 'nowrap', | ||
transition: 'opacity 0.3s ease-in-out, transform 0.3s ease-in-out', | ||
}); | ||
|
||
export const textVisible = style({ | ||
animation: `${fadeInText} 0.3s ease-out`, | ||
}); | ||
|
||
export const textHidden = style({ | ||
animation: `${fadeOutText} 0.3s ease-in`, | ||
opacity: 0, | ||
}); | ||
|
||
export const background = style({ | ||
position: 'fixed', | ||
top: 0, | ||
left: '50%', | ||
transform: 'translateX(-50%)', | ||
width: '100%', | ||
height: 'var(--height)', | ||
maxWidth: 'var(--max-width)', | ||
minWidth: 'var(--min-width)', | ||
transition: 'background-color 0.3s ease-in-out', | ||
}); | ||
|
||
// 전체 뷰포트 | ||
// export const background = style({ | ||
// position: 'fixed', | ||
// top: 0, | ||
// left: 0, | ||
// width: '100vw', | ||
// height: '100vh', | ||
// zIndex: themeVars.zIndex.floatingButton.content, | ||
// transition: 'background-color 0.3s ease-in-out', | ||
// }); | ||
|
||
export const backgroundVisible = style({ | ||
backgroundColor: themeVars.color.black_op, | ||
zIndex: themeVars.zIndex.floatingButton.content, | ||
}); |
128 changes: 128 additions & 0 deletions
128
apps/client/src/pages/time-table/components/edit-floating-button.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
import { useState } from 'react'; | ||
|
||
import { | ||
IcTimetableFloatClose, | ||
IcFloatEditLime24, | ||
IcFloatEdit24, | ||
IcFloatDelete24, | ||
IcTimetableFloatFinish, | ||
} from '@confeti/design-system/icons'; | ||
import * as styles from './edit-floating-button.css'; | ||
|
||
type ModeSetter = React.Dispatch<React.SetStateAction<boolean>>; | ||
|
||
interface RenderActionButtonProps { | ||
variant: 'close' | 'edit' | 'complete'; | ||
icon: JSX.Element; | ||
text: string | null; | ||
onClick: () => void; | ||
} | ||
|
||
const EditFloatingButton = () => { | ||
const [isEditMode, setIsEditMode] = useState(false); | ||
const [isEditTimeTableMode, setIsEditTimeTableMode] = useState(false); | ||
const [isFestivalDeleteMode, setIsFestivalDeleteMode] = useState(false); | ||
const [isTextVisible, setIsTextVisible] = useState(true); | ||
|
||
const resetModes = () => { | ||
setIsEditTimeTableMode(false); | ||
setIsFestivalDeleteMode(false); | ||
}; | ||
|
||
const handleToggleButton = () => { | ||
setIsEditMode((prev) => !prev); | ||
setIsTextVisible(true); | ||
if (isEditTimeTableMode || isFestivalDeleteMode) resetModes(); | ||
}; | ||
|
||
const handleModeToggle = (modeSetter: ModeSetter): void => { | ||
modeSetter((prev: boolean) => !prev); | ||
}; | ||
|
||
const getBackgroundClassName = () => { | ||
return `${styles.background} ${ | ||
isEditMode && !isEditTimeTableMode && !isFestivalDeleteMode | ||
? styles.backgroundVisible | ||
: '' | ||
}`; | ||
}; | ||
|
||
const renderButton = () => { | ||
if (isEditMode && (isEditTimeTableMode || isFestivalDeleteMode)) { | ||
return renderActionButton({ | ||
variant: 'complete', | ||
icon: <IcTimetableFloatFinish width="2.4rem" height="2.4rem" />, | ||
text: '완료하기', | ||
onClick: handleToggleButton, | ||
}); | ||
} | ||
|
||
if (isEditMode) { | ||
return renderActionButton({ | ||
variant: 'close', | ||
icon: <IcTimetableFloatClose width="2.4rem" height="2.4rem" />, | ||
text: null, | ||
onClick: handleToggleButton, | ||
}); | ||
} | ||
|
||
return renderActionButton({ | ||
variant: 'edit', | ||
icon: <IcFloatEditLime24 width="2.4rem" height="2.4rem" />, | ||
text: '편집하기', | ||
onClick: handleToggleButton, | ||
}); | ||
}; | ||
|
||
const renderActionButton = ({ | ||
variant, | ||
icon, | ||
text, | ||
onClick, | ||
}: RenderActionButtonProps) => ( | ||
<button className={styles.buttonVariants({ variant })} onClick={onClick}> | ||
{icon} | ||
{text && ( | ||
<span | ||
className={`${styles.text} ${isTextVisible ? styles.textVisible : styles.textHidden}`} | ||
> | ||
{text} | ||
</span> | ||
)} | ||
</button> | ||
); | ||
|
||
const renderActionButtons = () => { | ||
if (isEditMode && !isEditTimeTableMode && !isFestivalDeleteMode) { | ||
return ( | ||
<div className={styles.box}> | ||
<button | ||
onClick={() => handleModeToggle(setIsEditTimeTableMode)} | ||
className={styles.boxButton} | ||
> | ||
<IcFloatEdit24 width="2.4rem" height="2.4rem" /> | ||
<span>타임테이블 편집</span> | ||
</button> | ||
<button | ||
onClick={() => handleModeToggle(setIsFestivalDeleteMode)} | ||
className={styles.boxButton} | ||
> | ||
<IcFloatDelete24 width="2.4rem" height="2.4rem" /> | ||
<span>페스티벌 삭제</span> | ||
</button> | ||
</div> | ||
); | ||
} | ||
return null; | ||
}; | ||
|
||
return ( | ||
<> | ||
<div className={getBackgroundClassName()} /> | ||
{renderActionButtons()} | ||
{renderButton()} | ||
</> | ||
); | ||
}; | ||
|
||
export default EditFloatingButton; |