-
Notifications
You must be signed in to change notification settings - Fork 6
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
8 changed files
with
374 additions
and
4 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
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,115 @@ | ||
import { PropsWithChildren, ReactNode, useEffect, useState } from 'react'; | ||
import { css, Theme } from '@emotion/react'; | ||
import { motion, Variants } from 'framer-motion'; | ||
|
||
import PortalWrapper from '~/components/common/PortalWrapper'; | ||
import { defaultEasing, defaultFadeInUpVariants } from '~/constants/motions'; | ||
|
||
export interface DialogProps { | ||
isShowing?: boolean; | ||
actionButtons: ReactNode; | ||
} | ||
|
||
export default function Dialog({ | ||
isShowing, | ||
children, | ||
actionButtons, | ||
}: PropsWithChildren<DialogProps>) { | ||
const [isSSR, setIsSSR] = useState(true); | ||
|
||
useEffect(() => { | ||
setIsSSR(false); | ||
}, []); | ||
|
||
// NOTE: https://github.com/vercel/next.js/discussions/35773 | ||
if (!isSSR && isShowing) { | ||
return ( | ||
<PortalWrapper isShowing={true}> | ||
<motion.div | ||
css={dimBackdropCss} | ||
variants={backgroundFadeInOutVariants} | ||
initial="initial" | ||
animate="animate" | ||
exit="exit" | ||
> | ||
<motion.div css={dialogCss} variants={defaultFadeInUpVariants}> | ||
<div css={dialogContentWrapperCss}>{children}</div> | ||
<div css={dialogButtonWrapperCss}>{actionButtons}</div> | ||
</motion.div> | ||
</motion.div> | ||
</PortalWrapper> | ||
); | ||
} | ||
|
||
return <></>; | ||
} | ||
|
||
const dimBackdropCss = (theme: Theme) => css` | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
position: fixed; | ||
top: 0; | ||
left: 0; | ||
width: 100vw; | ||
height: 100vh; | ||
background-color: ${theme.color.dim03}; | ||
z-index: 10; | ||
overflow: hidden; | ||
`; | ||
|
||
const dialogCss = (theme: Theme) => css` | ||
position: relative; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
justify-content: flex-end; | ||
min-width: 300px; | ||
min-height: 200px; | ||
background-color: ${theme.color.background}; | ||
border-radius: ${theme.borderRadius.default}; | ||
`; | ||
|
||
const dialogContentWrapperCss = (theme: Theme) => css` | ||
white-space: pre; | ||
font-weight: ${theme.font.weight.bold}; | ||
font-style: normal; | ||
color: ${theme.color.gray05}; | ||
font-size: 16px; | ||
line-height: 150%; | ||
text-align: center; | ||
margin: 24px 16px; | ||
`; | ||
|
||
const dialogButtonWrapperCss = css` | ||
display: flex; | ||
flex-direction: row; | ||
gap: 16px; | ||
width: 100%; | ||
padding: 16px; | ||
`; | ||
|
||
export const backgroundFadeInOutVariants: Variants = { | ||
initial: { | ||
opacity: 0, | ||
transition: { duration: 0.2, ease: defaultEasing }, | ||
willChange: 'opacity', | ||
}, | ||
animate: { | ||
opacity: 1, | ||
transition: { duration: 0.2, ease: defaultEasing }, | ||
willChange: 'opacity', | ||
}, | ||
exit: { | ||
opacity: 0, | ||
transition: { duration: 0.2, ease: defaultEasing }, | ||
willChange: 'opacity', | ||
}, | ||
}; |
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
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
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,94 @@ | ||
import { css, Theme } from '@emotion/react'; | ||
|
||
import { CTAButton } from '~/components/common/Button'; | ||
import CheckList from '~/components/common/CheckList'; | ||
import NavigationBar from '~/components/common/NavigationBar'; | ||
import TextField from '~/components/common/TextField'; | ||
import useInput from '~/hooks/common/useInput'; | ||
|
||
export default function SignUpEmailVerified() { | ||
const nickname = useInput({ useDebounce: true }); | ||
const password = useInput({ useDebounce: true }); | ||
const passwordRepeat = useInput({ useDebounce: true }); | ||
|
||
return ( | ||
<article css={containerCss}> | ||
<NavigationBar title={'회원가입'} /> | ||
<p css={introTextWrapper}>마지막 단계입니다!</p> | ||
<form css={formCss}> | ||
<fieldset css={fieldSetCss}> | ||
<TextField | ||
label={'닉네임'} | ||
placeholder={'닉네임을 입력해주세요'} | ||
feedback={<> </>} | ||
value={nickname.value} | ||
onChange={nickname.onChange} | ||
required | ||
/> | ||
<TextField | ||
label={'비밀번호'} | ||
placeholder={'영문, 숫자 포함 6자 이상의 비밀번호'} | ||
feedback={<> </>} | ||
value={password.value} | ||
onChange={password.onChange} | ||
required | ||
/> | ||
<TextField | ||
label={'비밀번호 확인'} | ||
placeholder={'영문, 숫자 포함 6자 이상의 비밀번호'} | ||
feedback={<> </>} | ||
value={passwordRepeat.value} | ||
onChange={passwordRepeat.onChange} | ||
required | ||
/> | ||
<div css={checkListWrapperCss}> | ||
<CheckList isChecked={false} onToggle={() => {}}> | ||
(필수) 서비스 이용약관에 동의 | ||
</CheckList> | ||
<CheckList isChecked={false} onToggle={() => {}}> | ||
(필수) 개인정보 수집 이용에 동의 | ||
</CheckList> | ||
</div> | ||
</fieldset> | ||
<CTAButton type={'submit'}>Start Tang!</CTAButton> | ||
</form> | ||
</article> | ||
); | ||
} | ||
|
||
const containerCss = css` | ||
display: flex; | ||
flex-direction: column; | ||
height: 100%; | ||
`; | ||
|
||
const introTextWrapper = (theme: Theme) => css` | ||
white-space: pre; | ||
font-weight: ${theme.font.weight.bold}; | ||
color: ${theme.color.gray05}; | ||
font-size: 18px; | ||
line-height: 150%; | ||
margin-top: 40px; | ||
margin-bottom: 32px; | ||
`; | ||
|
||
const formCss = css` | ||
display: flex; | ||
flex-direction: column; | ||
justify-content: space-between; | ||
height: 100%; | ||
`; | ||
|
||
const fieldSetCss = css` | ||
display: flex; | ||
flex-direction: column; | ||
gap: 16px; // (original 36px) - (label height 20px) | ||
margin-bottom: 52px; | ||
`; | ||
|
||
const checkListWrapperCss = css` | ||
display: flex; | ||
flex-direction: column; | ||
`; |
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 |
---|---|---|
@@ -1,7 +1,76 @@ | ||
import { css } from '@emotion/react'; | ||
import { css, Theme } from '@emotion/react'; | ||
|
||
import { CTAButton } from '~/components/common/Button'; | ||
import NavigationBar from '~/components/common/NavigationBar'; | ||
import TextField from '~/components/common/TextField'; | ||
import useInput from '~/hooks/common/useInput'; | ||
|
||
export default function Signup() { | ||
return <article css={signupCss}>회원가입</article>; | ||
const email = useInput({ useDebounce: true }); | ||
|
||
return ( | ||
<article css={loginCss}> | ||
<NavigationBar title={'회원가입'} /> | ||
<div css={introCardCss}> | ||
<p css={introTextWrapper}> | ||
자주쓰는 이메일을 | ||
<br />딱 한번만 인증하면, | ||
<br /> | ||
영감을 차곡차곡 쌓아갈 수 있어요. | ||
</p> | ||
</div> | ||
<form css={fieldSetCss}> | ||
<TextField | ||
placeholder={'이메일을 입력해주세요'} | ||
feedback={<> </>} | ||
value={email.value} | ||
onChange={email.onChange} | ||
required | ||
/> | ||
<CTAButton type={'submit'}>로그인</CTAButton> | ||
</form> | ||
<div css={signUpTextWrapperCss}> | ||
입력한 이메일은 홍보/마케팅 용으로 사용되지 않고, | ||
<br /> | ||
로그인과 회원가입, 비밀번호 찾기에만 사용되니 안심하세요. | ||
</div> | ||
</article> | ||
); | ||
} | ||
|
||
const signupCss = css``; | ||
const loginCss = css` | ||
display: flex; | ||
flex-direction: column; | ||
`; | ||
|
||
const introCardCss = css` | ||
position: relative; | ||
width: 100%; | ||
height: 136px; | ||
margin-bottom: 36px; | ||
`; | ||
|
||
const introTextWrapper = (theme: Theme) => css` | ||
position: absolute; | ||
left: 12px; | ||
bottom: 17px; | ||
color: ${theme.color.gray05}; | ||
font-size: 15px; | ||
font-weight: 600; | ||
line-height: 150%; | ||
`; | ||
|
||
const fieldSetCss = css` | ||
display: flex; | ||
flex-direction: column; | ||
gap: 36px; | ||
margin-bottom: 52px; | ||
`; | ||
|
||
const signUpTextWrapperCss = (theme: Theme) => css` | ||
color: ${theme.color.gray03}; | ||
font-weight: ${theme.font.weight.regular}; | ||
font-size: 10px; | ||
line-height: 150%; | ||
text-align: center; | ||
`; |
Oops, something went wrong.