diff --git a/src/components/Confirm/Confirm.tsx b/src/components/Confirm/Confirm.tsx new file mode 100644 index 0000000..5234287 --- /dev/null +++ b/src/components/Confirm/Confirm.tsx @@ -0,0 +1,130 @@ +import styled from '@emotion/styled'; + +import theme from '../../styles/theme'; +import Flex from '../Flex/Flex'; +import Text from '../Text/Text'; + +interface ModalProps { + content: string; + closeButtonContent?: string; + confirmButtonContent?: string; + isOpen: boolean; + onClose: () => void; + onConfirm?: () => void; +} + +const Confirm = ({ + content, + closeButtonContent = '취소', + confirmButtonContent = '확인', + isOpen, + onClose, + onConfirm, +}: ModalProps) => { + const onClickConfirm = () => { + if (onConfirm) onConfirm(); + + onClose(); + }; + + return ( + <> + {isOpen && ( + + + + + {content} + + + {closeButtonContent !== '' && ( + + + {closeButtonContent} + + + )} + {confirmButtonContent !== '' && ( + + + {confirmButtonContent} + + + )} + + + + )} + + ); +}; + +export default Confirm; + +const Wrapper = styled.div` + display: flex; + justify-content: center; + align-items: center; + position: fixed; + height: 100%; + width: 100%; + inset: 0; + z-index: 10; +`; + +const ModalWrapper = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + width: 280px; + height: 167px; + border-radius: 14px; + box-shadow: + rgba(0, 0, 0, 0.2) 0px 11px 15px -7px, + rgba(0, 0, 0, 0.14) 0px 24px 38px 3px, + rgba(0, 0, 0, 0.12) 0px 9px 46px 8px; + background-color: #fff; + color: inherit; + z-index: 11; + white-space: pre-wrap; + word-break: keep-all; +`; + +const ContentWrapper = styled.div` + width: 149px; + text-align: center; + font-size: ${theme.font.suit14r.fontSize}px; + font-weight: ${theme.font.suit14r.fontWeight}; + line-height: 160%; +`; + +const Overlay = styled.div` + position: fixed; + display: flex; + align-items: center; + justify-content: center; + background-color: rgba(0, 0, 0, 0.54); + inset: 0; +`; diff --git a/src/stories/Confirm.stories.tsx b/src/stories/Confirm.stories.tsx new file mode 100644 index 0000000..d8f320a --- /dev/null +++ b/src/stories/Confirm.stories.tsx @@ -0,0 +1,77 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import Confirm from '../components/Confirm/Confirm'; +import { useEffect, useState } from 'react'; +import { Button, Flex } from '../../dist'; + +const meta = { + title: 'Components/Confirm', + component: Confirm, + tags: ['autodocs'], + argTypes: { + content: { + control: 'text', + description: 'Confirm 컴포넌트의 내용을 지정합니다.', + }, + closeButtonContent: { + control: 'text', + description: 'Confirm 컴포넌트의 닫기 버튼 텍스트를 지정합니다.', + }, + confirmButtonContent: { + control: 'text', + description: 'Confirm 컴포넌트의 확인 버튼 텍스트를 지정합니다.', + }, + isOpen: { + control: 'boolean', + description: 'Confirm 컴포넌트 표시 유무를 설정합니다.', + }, + onClose: { + control: false, + description: 'Confirm 컴포넌트를 닫을 때 사용하는 함수입니다.', + }, + onConfirm: { + control: false, + description: + 'Confirm 컴포넌트 확인 버튼 클릭 시 추가로 수행해야하는 동작을 지정할 수 있는 함수입니다.', + }, + }, +} as Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + content: 'Confirm 컴포넌트의 내용입니다.', + closeButtonContent: '취소', + confirmButtonContent: '확인', + isOpen: false, + }, + render: ({ content, closeButtonContent, confirmButtonContent, isOpen }) => { + const [isConfirmOpen, setIsConfirmOpen] = useState(isOpen); + + useEffect(() => { + setIsConfirmOpen(isOpen); + }, [isOpen]); + + return ( + <> + + + + +
+ setIsConfirmOpen(false)} + /> +
+ + ); + }, +};