Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/#550 Confirm Modal 구현 #553

Merged
merged 23 commits into from
Nov 23, 2023
Merged
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d3aee9e
feat: confirm provider 뼈대 구현
ukkodeveloper Nov 3, 2023
3a8246e
feat: confirm modal 수락 기능 추가
ukkodeveloper Nov 3, 2023
31ecdd0
feat: confirmModal 스타일 및 분리
ukkodeveloper Nov 4, 2023
580124d
feat: ConfirmProvider 분리
ukkodeveloper Nov 4, 2023
3273fa7
feat: ConfirmModal storybook 추가
ukkodeveloper Nov 4, 2023
c25781d
feat: storybook 예시 추가
ukkodeveloper Nov 5, 2023
d526aa9
refactor: useConfirm 분리
ukkodeveloper Nov 5, 2023
e382050
refactor: confirm modal 로직 응집하기 위해 useEffect 이동
ukkodeveloper Nov 5, 2023
a526142
fix: promise에서 resolve 함수 상태 변경 실패로 인한 ref 사용
ukkodeveloper Nov 5, 2023
1179f35
refactor: createPortal를 ConfirmModal 내부로 이동
ukkodeveloper Nov 5, 2023
dbc1c32
refactor: 의미있는 네이밍으로 변경
ukkodeveloper Nov 5, 2023
2af5e0b
fix: keydown 이벤트 적용되지 않는 현상 수정
ukkodeveloper Nov 6, 2023
6441a12
style: style lint 적용 및 개행
ukkodeveloper Nov 6, 2023
3f60df5
chore: 사용하지 않는 파일 삭제
ukkodeveloper Nov 14, 2023
a225ac0
fix: resolverRef 타입 변경
ukkodeveloper Nov 14, 2023
aab67ba
feat: 닫기, 수락 button에 type 추가
ukkodeveloper Nov 14, 2023
67963b6
refactor: 네이밍 cancel에서 denial으로 변경
ukkodeveloper Nov 14, 2023
b1ad8a7
feat: 모달 열릴 때 바로 title로 포커스 이동할 수 있도록 수정
ukkodeveloper Nov 14, 2023
ac5d64c
refactor: 중복된 createPortal 삭제
ukkodeveloper Nov 16, 2023
f27bd28
refactor: theme 활용하여 색상 코드 변경
ukkodeveloper Nov 17, 2023
a6eb162
refactor: 전반적인 ConfirmModal 네이밍 변경
ukkodeveloper Nov 17, 2023
a2fb196
fix: theme color 사용 시 객체분해할당 오류 수정
ukkodeveloper Nov 17, 2023
b94ea94
Merge branch 'main' into feat/#550
ukkodeveloper Nov 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: confirmModal 스타일 및 분리
ukkodeveloper committed Nov 4, 2023
commit 31ecdd03c1251d3699b05e2d8e9631629b00030a
172 changes: 94 additions & 78 deletions frontend/src/shared/components/ConfirmModal/ConfirmModal.tsx
Original file line number Diff line number Diff line change
@@ -1,95 +1,111 @@
import { createContext, useState } from 'react';
import { createPortal } from 'react-dom';
import { useEffect } from 'react';
import { Flex } from 'shook-layout';
import styled from 'styled-components';
import styled, { css } from 'styled-components';
import Spacing from '../Spacing';
import type { ReactNode } from 'react';

const ConfirmContext = createContext<null | {
getConfirmation: (modalState: ModalState) => Promise<boolean>;
}>(null);

const Backdrop = styled.div``;
const ContainerFlex = styled(Flex)``;
const ButtonFlex = styled(Flex)``;
const Title = styled.header``;
const Content = styled.div``;
const CancelButton = styled.button``;
const ConfirmButton = styled.button``;

interface ModalState {
interface ConfirmModalProps {
title: string;
content: ReactNode;
cancelName?: string;
confirmName?: string;
cancelName: string;
confirmName: string;
onCancel: () => void;
onConfirm: () => void;
onKeyDown: (event: KeyboardEvent) => void;
}

type Resolver<T> = (value: T) => void;
const ConfirmModal = ({
title,
content,
cancelName,
confirmName,
onCancel,
onConfirm,
onKeyDown,
}: ConfirmModalProps) => {
useEffect(() => {
document.addEventListener('keydown', onKeyDown);
document.body.style.overflow = 'hidden';

const createPromise = <T,>() => {
let resolver: Resolver<T> | null = null;
const promise = new Promise<T>((resolve) => {
resolver = resolve;
});
return () => {
document.removeEventListener('keydown', onKeyDown);
document.body.style.overflow = 'auto';
};
}, []);

return { promise, resolver };
return (
<>
<Backdrop role="dialog" aria-modal="true" />
<Container>
<Title>{title}</Title>
<Spacing direction="vertical" size={10} />
<Content>{content}</Content>
<Spacing direction="vertical" size={10} />
<ButtonFlex $gap={16}>
<CancelButton onClick={onCancel}>{cancelName}</CancelButton>
<ConfirmButton onClick={onConfirm}>{confirmName}</ConfirmButton>
</ButtonFlex>
</Container>
</>
);
};

const ConfirmProvider = (children: ReactNode) => {
const [isOpen, setIsOpen] = useState(false);
const [resolve, setResolve] = useState<((value: boolean) => void) | null>(null);
const [modalState, setModalState] = useState<ModalState>({
title: '',
content: '',
cancelName: '닫기',
confirmName: '확인',
});
const { title, content, cancelName, confirmName } = modalState;
export default ConfirmModal;

const getConfirmation = ({
cancelName = '닫기',
confirmName = '확인',
...restState
}: ModalState): Promise<boolean> => {
const { promise, resolver } = createPromise<boolean>();
setResolve(resolver);
setModalState({
cancelName,
confirmName,
...restState,
});
setIsOpen(true);
const Backdrop = styled.div`
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
Comment on lines +54 to +57
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inset 으로 1줄로 줄여볼까용~?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋아요!


return promise;
};
width: 100%;
height: 100%;
margin: 0;
padding: 0;

const onClick = (status: boolean) => {
setIsOpen(false);
background-color: rgba(0, 0, 0, 0.7);
`;

if (resolve) {
resolve(status);
}
};
const Container = styled.section`
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

return (
<ConfirmContext.Provider value={{ getConfirmation }}>
{children}
{isOpen &&
createPortal(
<>
<Backdrop />
<ContainerFlex>
<Title>{title}</Title>
<Content>{content}</Content>
<ButtonFlex>
<CancelButton onClick={() => onClick(false)}>{cancelName}</CancelButton>
<ConfirmButton onClick={() => onClick(true)}>{confirmName}</ConfirmButton>
</ButtonFlex>
</ContainerFlex>
</>,
document.body
)}
</ConfirmContext.Provider>
);
};
min-width: 300px;
margin: 0 auto;
padding: 24px;

color: #ffffff;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💬 theme .color.white 레츠고우~

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이것도 함께 이야기 나누면 좋을 것 같아용. 항상 color 값 줄때마다 ${({theme}) => theme.color.white}를 적는 게 불편한데 도밥은 어떠신가요? 저는 차라리 객체로 관리하는 게 낫지 않을까 생각도 듭니다.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

공감합니다. 테마를 동적으로 바꾸는 일도 없어서 더욱더 그렇네용
다만 일단은 컨벤션에 맞게 작성해두고, 한번에 바꾸는게 좋을 것 같아요

저도 현 구조에서 theme의 장점이 있을지 한번 더 생각해볼게요!
(한번 생각해봤는데 우선은 없네요 ㅋㅋㅋ...)


background-color: #17171c;
border: none;
border-radius: 16px;
`;
const ButtonFlex = styled(Flex)`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`;
const ButtonFlex = styled(Flex)`
`;
const ButtonFlex = styled(Flex)`

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

개행 부분이랑 style lint 수정완료 했어요

width: 100%;
`;
const Title = styled.header`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`;
const Title = styled.header`
`;
const Title = styled.header`

text-align: left;
font-size: 18px;
`;
const Content = styled.div``;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`;
const Content = styled.div``;
`;
const Content = styled.div``;


const buttonStyle = css`
flex: 1;
height: 36px;
color: ${({ theme: { color } }) => color.white};
width: 100%;

border-radius: 10px;
`;

export default ConfirmProvider;
const CancelButton = styled.button`
background-color: ${({ theme: { color } }) => color.secondary};
${buttonStyle}
`;
const ConfirmButton = styled.button`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`;
const ConfirmButton = styled.button`
`;
const ConfirmButton = styled.button`

background-color: ${({ theme: { color } }) => color.primary};
${buttonStyle}
`;