Skip to content

Commit

Permalink
[Design] Mobile ver. - Dialog 구현 (#392)
Browse files Browse the repository at this point in the history
* design: dialog 반응형 크기 구현

* design: dialog 반응형 구현

* chore: dialogs import 방식 통일

* design: dialog 버튼 font 반응형으로 수정
  • Loading branch information
eonseok-jeon authored Aug 14, 2024
1 parent ea7721a commit 3179b95
Show file tree
Hide file tree
Showing 17 changed files with 296 additions and 71 deletions.
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import Layout from '@components/Layout';
import { RecruitingInfoContext, RecruitingInfoType } from '@store/recruitingInfoContext';
import { ModeType, ThemeContext } from '@store/themeContext';
import { dark, light } from 'styles/theme.css';
import SessionExpiredDialog from 'views/dialogs/SessionExpiredDialog';
import ErrorPage from 'views/ErrorPage';
import MainPage from 'views/MainPage';
import PasswordPage from 'views/PasswordPage';
Expand All @@ -21,6 +20,7 @@ import ReviewPage from 'views/ReviewPage';
import SignupPage from 'views/SignupPage';

import 'styles/reset.css';
import { SessionExpiredDialog } from 'views/dialogs';

const router = createBrowserRouter([
{
Expand Down
8 changes: 6 additions & 2 deletions src/common/components/Dialog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { forwardRef, type DialogHTMLAttributes, type ReactNode } from 'react';
import { createPortal } from 'react-dom';

import { container } from './style.css';
import { useDevice } from '@hooks/useDevice';

import { containerVar } from './style.css';

interface DialogProps extends DialogHTMLAttributes<HTMLDialogElement> {
children?: ReactNode;
}

const Dialog = forwardRef<HTMLDialogElement, DialogProps>(({ children, ...dialogElementProps }: DialogProps, ref) => {
const DEVICE_TYPE = useDevice();

return createPortal(
<dialog ref={ref} className={container} {...dialogElementProps}>
<dialog ref={ref} className={containerVar[DEVICE_TYPE]} {...dialogElementProps}>
{children}
</dialog>,
document.getElementById('modal')!,
Expand Down
26 changes: 23 additions & 3 deletions src/common/components/Dialog/style.css.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { colors } from '@sopt-makers/colors';
import { style } from '@vanilla-extract/css';
import { style, styleVariants } from '@vanilla-extract/css';

export const container = style({
width: 400,
const container = style({
padding: 24,
backgroundColor: colors.white, // subBackground
borderRadius: 14,
Expand All @@ -12,3 +11,24 @@ export const container = style({
backgroundColor: colors.grayAlpha500, // backgroundDimmed
},
});

export const containerVar = styleVariants({
DESK: [
container,
{
width: 400,
},
],
TAB: [
container,
{
width: 400,
},
],
MOB: [
container,
{
width: 313,
},
],
});
3 changes: 1 addition & 2 deletions src/views/ApplyPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import Footer from '@components/Layout/components/Footer';
import useCheckBrowser from '@hooks/useCheckBrowser';
import useDate from '@hooks/useDate';
import useScrollToHash from '@hooks/useScrollToHash';
import { DraftDialog, SubmitDialog } from 'views/dialogs';
import PreventApplyDialog from 'views/dialogs/PreventApplyDialog';
import { DraftDialog, PreventApplyDialog, SubmitDialog } from 'views/dialogs';
import NoMore from 'views/ErrorPage/components/NoMore';
import BigLoading from 'views/loadings/BigLoding';

Expand Down
2 changes: 1 addition & 1 deletion src/views/ReviewPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import PartSection from 'views/ApplyPage/components/PartSection';
import useGetDraft from 'views/ApplyPage/hooks/useGetDraft';
import useGetQuestions from 'views/ApplyPage/hooks/useGetQuestions';
import { container, formContainer } from 'views/ApplyPage/style.css';
import PreventReviewDialog from 'views/dialogs/PreventReviewDialog';
import { PreventReviewDialog } from 'views/dialogs';
import NoMore from 'views/ErrorPage/components/NoMore';
import BigLoading from 'views/loadings/BigLoding';

Expand Down
2 changes: 1 addition & 1 deletion src/views/SignupPage/components/SignupForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { PRIVACY_POLICY } from '@constants/policy';
import { VALIDATION_CHECK } from '@constants/validationCheck';
import useVerificationStatus from '@hooks/useVerificationStatus';
import { RecruitingInfoContext } from '@store/recruitingInfoContext';
import ExistingApplicantDialog from 'views/dialogs/ExistingApplicantDialog';
import { ExistingApplicantDialog } from 'views/dialogs';
import useMutateSignUp from 'views/SignupPage/hooks/useMutateSignUp';

import { formWrapper } from './style.css';
Expand Down
13 changes: 9 additions & 4 deletions src/views/dialogs/CompleteDialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@ import { forwardRef } from 'react';
import { Link } from 'react-router-dom';

import Dialog from '@components/Dialog';
import { useDevice } from '@hooks/useDevice';

import { buttonInside, buttonOutside, buttonWrapper, mainText, subText } from '../style.css';
import { buttonInside, buttonOutside, buttonOutsideVar, buttonWrapperVar, mainTextVar, subTextVar } from '../style.css';

const CompleteDialog = forwardRef<HTMLDialogElement>((_, ref) => {
const DEVICE_TYPE = useDevice();

return (
<Dialog ref={ref}>
<p className={mainText}>비밀번호 재설정이 완료되었어요.</p>
<p className={subText}>&apos;로그인&apos; 페이지로 이동할게요.</p>
<form method="dialog" className={`${buttonWrapper} ${buttonOutside.solid}`}>
<p className={mainTextVar[DEVICE_TYPE]}>비밀번호 재설정이 완료되었어요.</p>
<p className={subTextVar[DEVICE_TYPE]}>&apos;로그인&apos; 페이지로 이동할게요.</p>
<form
method="dialog"
className={`${buttonWrapperVar[DEVICE_TYPE]} ${buttonOutside.solid} ${buttonOutsideVar[DEVICE_TYPE]}`}>
<Link to="/" className={buttonInside.solid}>
확인
</Link>
Expand Down
11 changes: 8 additions & 3 deletions src/views/dialogs/DraftDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { forwardRef } from 'react';

import Dialog from '@components/Dialog';
import { useDevice } from '@hooks/useDevice';

import { buttonInside, buttonOutside, buttonWrapper, mainText } from '../style.css';
import { buttonInside, buttonOutside, buttonOutsideVar, buttonWrapperVar, mainTextVar } from '../style.css';

const DraftDialog = forwardRef<HTMLDialogElement>((_, ref) => {
const DEVICE_TYPE = useDevice();

return (
<Dialog ref={ref}>
<p className={mainText}>임시 저장이 완료되었어요.</p>
<form method="dialog" className={`${buttonWrapper} ${buttonOutside.solid}`}>
<p className={mainTextVar[DEVICE_TYPE]}>임시 저장이 완료되었어요.</p>
<form
method="dialog"
className={`${buttonWrapperVar[DEVICE_TYPE]} ${buttonOutside.solid} ${buttonOutsideVar[DEVICE_TYPE]}`}>
<button className={buttonInside.solid}>확인</button>
</form>
</Dialog>
Expand Down
11 changes: 7 additions & 4 deletions src/views/dialogs/ExistingApplicantDialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ import { forwardRef } from 'react';
import { Link } from 'react-router-dom';

import Dialog from '@components/Dialog';
import { useDevice } from '@hooks/useDevice';

import { buttonInside, buttonOutside, buttonWrapper, mainText } from '../style.css';
import { buttonInside, buttonOutside, buttonOutsideVar, buttonWrapperVar, mainTextVar } from '../style.css';

const ExistingApplicantDialog = forwardRef<HTMLDialogElement>((_, ref) => {
const DEVICE_TYPE = useDevice();

return (
<Dialog ref={ref}>
<p className={mainText}>이미 가입된 계정이 있어요.</p>
<div className={buttonWrapper}>
<form method="dialog" className={buttonOutside.line}>
<p className={mainTextVar[DEVICE_TYPE]}>이미 가입된 계정이 있어요.</p>
<div className={buttonWrapperVar[DEVICE_TYPE]}>
<form method="dialog" className={`${buttonOutside.line} ${buttonOutsideVar[DEVICE_TYPE]}`}>
<button className={buttonInside.line}>다시 입력하기</button>
</form>
<div className={buttonOutside.solid}>
Expand Down
15 changes: 9 additions & 6 deletions src/views/dialogs/ExitDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import { forwardRef } from 'react';

import Dialog from '@components/Dialog';
import { useDevice } from '@hooks/useDevice';

import { buttonInside, buttonOutside, buttonWrapper, mainText, subText } from '../style.css';
import { buttonInside, buttonOutside, buttonOutsideVar, buttonWrapperVar, mainTextVar, subTextVar } from '../style.css';

const ExitDialog = forwardRef<HTMLDialogElement>((_, ref) => {
const DEVICE_TYPE = useDevice();

return (
<Dialog ref={ref}>
<p className={mainText}>이대로 나가시겠어요?</p>
<p className={subText}>변경사항이 있는 경우 임시저장을 해주세요.</p>
<div className={buttonWrapper}>
<form method="dialog" className={buttonOutside.line}>
<p className={mainTextVar[DEVICE_TYPE]}>이대로 나가시겠어요?</p>
<p className={subTextVar[DEVICE_TYPE]}>변경사항이 있는 경우 임시저장을 해주세요.</p>
<div className={buttonWrapperVar[DEVICE_TYPE]}>
<form method="dialog" className={`${buttonOutside.line} ${buttonOutsideVar[DEVICE_TYPE]}`}>
<button className={buttonInside.line}>머물기</button>
</form>
<div className={buttonOutside.solid}>
<div className={`${buttonOutside.solid} ${buttonOutsideVar[DEVICE_TYPE]}`}>
<button className={buttonInside.solid}>나가기</button>
</div>
</div>
Expand Down
11 changes: 8 additions & 3 deletions src/views/dialogs/PreventApplyDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import { forwardRef, type KeyboardEvent } from 'react';

import Dialog from '@components/Dialog';
import { useDevice } from '@hooks/useDevice';

import { buttonInside, buttonOutside, buttonWrapper, mainText } from '../style.css';
import { buttonInside, buttonOutside, buttonOutsideVar, buttonWrapperVar, mainTextVar } from '../style.css';

const PreventApplyDialog = forwardRef<HTMLDialogElement>((_, ref) => {
const DEVICE_TYPE = useDevice();

const handlePreventESCKeyPress = (e: KeyboardEvent<HTMLDialogElement>) => {
if (e.key === 'Escape') e.preventDefault();
};

return (
<Dialog ref={ref} onKeyDown={handlePreventESCKeyPress}>
<p className={mainText}>지원서 제출 기한이 지났어요.</p>
<form method="dialog" className={`${buttonWrapper} ${buttonOutside.solid}`}>
<p className={mainTextVar[DEVICE_TYPE]}>지원서 제출 기한이 지났어요.</p>
<form
method="dialog"
className={`${buttonWrapperVar[DEVICE_TYPE]} ${buttonOutside.solid} ${buttonOutsideVar[DEVICE_TYPE]}`}>
<button className={buttonInside.solid}>확인</button>
</form>
</Dialog>
Expand Down
13 changes: 9 additions & 4 deletions src/views/dialogs/PreventReviewDialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@ import { forwardRef, type KeyboardEvent } from 'react';
import { Link } from 'react-router-dom';

import Dialog from '@components/Dialog';
import { useDevice } from '@hooks/useDevice';

import { buttonInside, buttonOutside, buttonWrapper, mainText, subText } from '../style.css';
import { buttonInside, buttonOutside, buttonOutsideVar, buttonWrapperVar, mainTextVar, subTextVar } from '../style.css';

const PreventReviewDialog = forwardRef<HTMLDialogElement>((_, ref) => {
const DEVICE_TYPE = useDevice();

const handlePreventESCKeyPress = (e: KeyboardEvent<HTMLDialogElement>) => {
if (e.key === 'Escape') e.preventDefault();
};

return (
<Dialog ref={ref} onKeyDown={handlePreventESCKeyPress}>
<p className={mainText}>지원서 제출을 먼저 해주세요.</p>
<p className={subText}>&apos;지원서&apos; 페이지로 이동할게요.</p>
<form method="dialog" className={`${buttonWrapper} ${buttonOutside.solid}`}>
<p className={mainTextVar[DEVICE_TYPE]}>지원서 제출을 먼저 해주세요.</p>
<p className={subTextVar[DEVICE_TYPE]}>&apos;지원서&apos; 페이지로 이동할게요.</p>
<form
method="dialog"
className={`${buttonWrapperVar[DEVICE_TYPE]} ${buttonOutside.solid} ${buttonOutsideVar[DEVICE_TYPE]}`}>
<Link to="/" className={buttonInside.solid}>
확인
</Link>
Expand Down
13 changes: 9 additions & 4 deletions src/views/dialogs/SessionExpiredDialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import { track } from '@amplitude/analytics-browser';
import { forwardRef, type KeyboardEvent } from 'react';

import Dialog from '@components/Dialog';
import { useDevice } from '@hooks/useDevice';

import { buttonInside, buttonOutside, buttonWrapper, mainText, subText } from '../style.css';
import { buttonInside, buttonOutside, buttonOutsideVar, buttonWrapperVar, mainTextVar, subTextVar } from '../style.css';

const SessionExpiredDialog = forwardRef<HTMLDialogElement>((_, ref) => {
const DEVICE_TYPE = useDevice();

const handlePreventESCKeyPress = (e: KeyboardEvent<HTMLDialogElement>) => {
if (e.key === 'Escape') e.preventDefault();
};
Expand All @@ -23,9 +26,11 @@ const SessionExpiredDialog = forwardRef<HTMLDialogElement>((_, ref) => {

return (
<Dialog ref={ref} onKeyDown={handlePreventESCKeyPress}>
<p className={mainText}>로그인을 다시 해주세요.</p>
<p className={subText}>세션이 만료되었거나 비정상적인 로그인이에요.</p>
<form method="dialog" className={`${buttonWrapper} ${buttonOutside.solid}`}>
<p className={mainTextVar[DEVICE_TYPE]}>로그인을 다시 해주세요.</p>
<p className={subTextVar[DEVICE_TYPE]}>세션이 만료되었거나 비정상적인 로그인이에요.</p>
<form
method="dialog"
className={`${buttonWrapperVar[DEVICE_TYPE]} ${buttonOutside.solid} ${buttonOutsideVar[DEVICE_TYPE]}`}>
<button className={buttonInside.solid} onClick={handleLogout}>
확인
</button>
Expand Down
49 changes: 30 additions & 19 deletions src/views/dialogs/SubmitDialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,34 @@ import { track } from '@amplitude/analytics-browser';
import { type ChangeEvent, forwardRef, useState } from 'react';

import Dialog from '@components/Dialog';
import { useDevice } from '@hooks/useDevice';
import ButtonLoading from 'views/loadings/ButtonLoading';

import {
checkboxContainer,
checkboxWrapper,
checkmark,
hiddenCheckbox,
infoContainer,
infoLabel,
infoValue,
infoWrapper,
infoContainerVar,
infoLabelVar,
infoValueVar,
infoWrapperVar,
} from './style.css';
import { buttonInside, buttonOutside, buttonWrapper, mainText, subText } from '../style.css';
import { buttonInside, buttonOutside, buttonOutsideVar, buttonWrapperVar, mainTextVar, subTextVar } from '../style.css';

const MyInfoItem = ({ label, value }: { label: string; value: string }) => {
const MyInfoItem = ({
DEVICE_TYPE,
label,
value,
}: {
DEVICE_TYPE: 'MOB' | 'TAB' | 'DESK';
label: string;
value: string;
}) => {
return (
<li className={infoWrapper}>
<label className={infoLabel}>{label}</label>
<span className={infoValue}>{value}</span>
<li className={infoWrapperVar[DEVICE_TYPE]}>
<label className={infoLabelVar[DEVICE_TYPE]}>{label}</label>
<span className={infoValueVar[DEVICE_TYPE]}>{value}</span>
</li>
);
};
Expand All @@ -40,19 +49,21 @@ const SubmitDialog = forwardRef<HTMLDialogElement, SubmitDialogProps>(
({ userInfo: { name, email, phone, part }, dataIsPending, onSendData }, ref) => {
const [isChecked, setIsChecked] = useState(false);

const DEVICE_TYPE = useDevice();

const handleCheck = (e: ChangeEvent<HTMLInputElement>) => {
setIsChecked(e.target.checked);
};

return (
<Dialog ref={ref}>
<p className={mainText}>이대로 제출하시겠어요?</p>
<p className={subText}>제출 완료하신 지원서는 수정하실 수 없어요.</p>
<ol className={infoContainer}>
<MyInfoItem label="이름" value={name} />
<MyInfoItem label="이메일" value={email} />
<MyInfoItem label="전화번호" value={phone} />
<MyInfoItem label="지원파트" value={part} />
<p className={mainTextVar[DEVICE_TYPE]}>이대로 제출하시겠어요?</p>
<p className={subTextVar[DEVICE_TYPE]}>제출 완료하신 지원서는 수정하실 수 없어요.</p>
<ol className={infoContainerVar[DEVICE_TYPE]}>
<MyInfoItem DEVICE_TYPE={DEVICE_TYPE} label="이름" value={name} />
<MyInfoItem DEVICE_TYPE={DEVICE_TYPE} label="이메일" value={email} />
<MyInfoItem DEVICE_TYPE={DEVICE_TYPE} label="전화번호" value={phone} />
<MyInfoItem DEVICE_TYPE={DEVICE_TYPE} label="지원파트" value={part} />
</ol>
<div className={checkboxContainer}>
<label className={checkboxWrapper}>
Expand All @@ -66,16 +77,16 @@ const SubmitDialog = forwardRef<HTMLDialogElement, SubmitDialogProps>(
<span>확인했습니다.</span>
</label>
</div>
<div className={buttonWrapper}>
<div className={buttonWrapperVar[DEVICE_TYPE]}>
<form
method="dialog"
className={dataIsPending ? buttonOutside.disabled : buttonOutside.line}
className={`${dataIsPending ? buttonOutside.disabled : buttonOutside.line} ${buttonOutsideVar[DEVICE_TYPE]}`}
onSubmit={() => setIsChecked(false)}>
<button className={buttonInside.line} disabled={dataIsPending} onClick={() => track('click-apply-cancel')}>
{dataIsPending ? <ButtonLoading width={48} height={18} /> : '검토하기'}
</button>
</form>
<div className={buttonOutside[!isChecked ? 'disabled' : 'solid']}>
<div className={`${buttonOutside[!isChecked ? 'disabled' : 'solid']} ${buttonOutsideVar[DEVICE_TYPE]}`}>
<button className={buttonInside.solid} onClick={onSendData} disabled={!isChecked || dataIsPending}>
{dataIsPending ? <ButtonLoading width={48} height={18} /> : '제출하기'}
</button>
Expand Down
Loading

0 comments on commit 3179b95

Please sign in to comment.