-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: 모달 UI 컴포넌트 구현, storybook 작성 * fix: useDisclosure 훅 별도 구현 및 모달의 컨텐츠 영역 분리 * fix: storybook delete 내용 수정 * chore: fragment 삭제 * fix: px단위를 rem단위로 변경 및 피그마 디자인에 맞게 모달 배경색 및 투명도 변경
- Loading branch information
1 parent
91ce726
commit e5f8fcd
Showing
3 changed files
with
147 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { useState } from 'react'; | ||
|
||
const useDisclosure = () => { | ||
const [isOpen, setIsOpen] = useState<boolean>(false); | ||
|
||
const onOpen = () => { | ||
setIsOpen(true); | ||
}; | ||
|
||
const onClose = () => { | ||
setIsOpen(false); | ||
}; | ||
|
||
return { isOpen, onOpen, onClose }; | ||
}; | ||
|
||
export default useDisclosure; |
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,82 @@ | ||
import { Meta, StoryObj } from '@storybook/react'; | ||
import Modal from '@/ui/Base/Modal'; | ||
import useDisclosure from '@/hooks/useDisclosure'; | ||
import Button from '@/ui/Base/Button'; | ||
import { Fragment } from 'react'; | ||
|
||
const meta: Meta<typeof Modal> = { | ||
title: 'Base/Modal', | ||
component: Modal, | ||
tags: ['autodocs'], | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof Modal>; | ||
|
||
const BaseModal = () => { | ||
const { isOpen, onOpen, onClose } = useDisclosure(); | ||
|
||
return ( | ||
<> | ||
<Button | ||
onClick={() => { | ||
onOpen(); | ||
}} | ||
> | ||
Open Modal | ||
</Button> | ||
<Modal isOpen={isOpen} onClose={onClose}></Modal> | ||
</> | ||
); | ||
}; | ||
|
||
const DeleteModal = () => { | ||
const { isOpen, onOpen, onClose } = useDisclosure(); | ||
|
||
const handleClick = () => { | ||
alert('삭제되었습니다.'); | ||
onClose(); | ||
}; | ||
|
||
return ( | ||
<> | ||
<Button | ||
onClick={() => { | ||
onOpen(); | ||
}} | ||
> | ||
Open Modal | ||
</Button> | ||
<Modal isOpen={isOpen} onClose={onClose}> | ||
<div className="text-lg font-bold"> | ||
정말 삭제할까요? | ||
<p className="text-xs font-normal text-black-500"> | ||
한번 삭제하면 되돌릴 수 없어요. | ||
</p> | ||
</div> | ||
<div className="flex justify-end gap-[1rem]"> | ||
<Button | ||
onClick={onClose} | ||
fill={false} | ||
colorScheme="grey" | ||
size="small" | ||
> | ||
취소 | ||
</Button> | ||
<Button onClick={handleClick} size="small"> | ||
확인 | ||
</Button> | ||
</div> | ||
</Modal> | ||
</> | ||
); | ||
}; | ||
|
||
export const Default: Story = { | ||
render: () => <BaseModal />, | ||
}; | ||
|
||
export const Delete: Story = { | ||
render: () => <DeleteModal />, | ||
}; |
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,48 @@ | ||
import { Dialog, Transition } from '@headlessui/react'; | ||
import { Fragment, ReactNode } from 'react'; | ||
|
||
interface ModalProps { | ||
isOpen: boolean; | ||
onClose: () => void; | ||
children?: ReactNode; | ||
} | ||
|
||
const Modal = ({ isOpen, onClose, children }: ModalProps) => { | ||
return ( | ||
<Transition appear show={isOpen} as={Fragment}> | ||
<Dialog as="div" className="relative z-10" onClose={onClose}> | ||
<Transition.Child | ||
as={Fragment} | ||
enter="ease-out duration-300" | ||
enterFrom="opacity-0" | ||
enterTo="opacity-100" | ||
leave="ease-in duration-200" | ||
leaveFrom="opacity-100" | ||
leaveTo="opacity-0" | ||
> | ||
<div className="fixed inset-0 bg-overlay bg-opacity-60" /> | ||
</Transition.Child> | ||
|
||
<div className="fixed inset-0 overflow-y-auto"> | ||
<div className="flex min-h-full items-center justify-center"> | ||
<Transition.Child | ||
as={Fragment} | ||
enter="ease-out duration-300" | ||
enterFrom="opacity-0 scale-95" | ||
enterTo="opacity-100 scale-100" | ||
leave="ease-in duration-200" | ||
leaveFrom="opacity-100 scale-100" | ||
leaveTo="opacity-0 scale-95" | ||
> | ||
<Dialog.Panel className="flex w-[31.3rem] transform flex-col gap-[2.5rem] overflow-hidden rounded-[0.4rem] bg-white px-[2.5rem] py-[2rem] transition-all"> | ||
{children} | ||
</Dialog.Panel> | ||
</Transition.Child> | ||
</div> | ||
</div> | ||
</Dialog> | ||
</Transition> | ||
); | ||
}; | ||
|
||
export default Modal; |