143 lines
4.4 KiB
TypeScript
143 lines
4.4 KiB
TypeScript
import type { Meta, StoryObj } from '@storybook/react'
|
|
import { useState } from 'react'
|
|
import { Button } from '../button/Button'
|
|
import { ModalBody, ModalFooter, ModalHeader, ModalRoot } from './Modal'
|
|
|
|
const meta = {
|
|
title: 'Components/Modal',
|
|
component: ModalRoot,
|
|
argTypes: {
|
|
isDismissable: { control: 'boolean' },
|
|
isKeyboardDismissDisabled: { control: 'boolean' },
|
|
},
|
|
} satisfies Meta<typeof ModalRoot>
|
|
|
|
export default meta
|
|
type Story = StoryObj<typeof meta>
|
|
|
|
export const Default: Story = {
|
|
render: function Render() {
|
|
const [isOpen, setIsOpen] = useState(false)
|
|
return (
|
|
<>
|
|
<Button onClick={() => setIsOpen(true)}>모달 열기</Button>
|
|
<ModalRoot isOpen={isOpen} onOpenChange={setIsOpen}>
|
|
<ModalHeader>모달 제목</ModalHeader>
|
|
<ModalBody>
|
|
<p className="text-sm">모달 내용입니다.</p>
|
|
</ModalBody>
|
|
<ModalFooter>
|
|
<Button color="gray" size="large" onClick={() => setIsOpen(false)}>
|
|
취소
|
|
</Button>
|
|
<Button color="primary" size="large" onClick={() => setIsOpen(false)}>
|
|
확인
|
|
</Button>
|
|
</ModalFooter>
|
|
</ModalRoot>
|
|
</>
|
|
)
|
|
},
|
|
}
|
|
|
|
export const WithoutCloseButton: Story = {
|
|
render: function Render() {
|
|
const [isOpen, setIsOpen] = useState(false)
|
|
return (
|
|
<>
|
|
<Button onClick={() => setIsOpen(true)}>모달 열기</Button>
|
|
<ModalRoot isOpen={isOpen} onOpenChange={setIsOpen}>
|
|
<ModalHeader hasCloseButton={false}>닫기 버튼 없음</ModalHeader>
|
|
<ModalBody>
|
|
<p className="text-sm">헤더에 닫기 버튼이 없습니다.</p>
|
|
</ModalBody>
|
|
<ModalFooter>
|
|
<Button color="primary" size="large" onClick={() => setIsOpen(false)}>
|
|
확인
|
|
</Button>
|
|
</ModalFooter>
|
|
</ModalRoot>
|
|
</>
|
|
)
|
|
},
|
|
}
|
|
|
|
export const LongContent: Story = {
|
|
render: function Render() {
|
|
const [isOpen, setIsOpen] = useState(false)
|
|
return (
|
|
<>
|
|
<Button onClick={() => setIsOpen(true)}>모달 열기</Button>
|
|
<ModalRoot isOpen={isOpen} onOpenChange={setIsOpen}>
|
|
<ModalHeader>긴 내용</ModalHeader>
|
|
<ModalBody className="max-h-60 overflow-y-auto">
|
|
{Array.from({ length: 20 }, (_, i) => (
|
|
<p key={i} className="text-sm mb-2">
|
|
내용 {i + 1}: Lorem ipsum dolor sit amet consectetur adipisicing elit.
|
|
</p>
|
|
))}
|
|
</ModalBody>
|
|
<ModalFooter>
|
|
<Button color="primary" size="large" onClick={() => setIsOpen(false)}>
|
|
확인
|
|
</Button>
|
|
</ModalFooter>
|
|
</ModalRoot>
|
|
</>
|
|
)
|
|
},
|
|
}
|
|
|
|
export const NotDismissable: Story = {
|
|
render: function Render() {
|
|
const [isOpen, setIsOpen] = useState(false)
|
|
return (
|
|
<>
|
|
<Button onClick={() => setIsOpen(true)}>모달 열기</Button>
|
|
<ModalRoot
|
|
isOpen={isOpen}
|
|
onOpenChange={setIsOpen}
|
|
isDismissable={false}
|
|
isKeyboardDismissDisabled={true}
|
|
>
|
|
<ModalHeader hasCloseButton={false}>닫을 수 없음</ModalHeader>
|
|
<ModalBody>
|
|
<p className="text-sm">배경 클릭이나 ESC로 닫을 수 없습니다.</p>
|
|
</ModalBody>
|
|
<ModalFooter>
|
|
<Button color="primary" size="large" onClick={() => setIsOpen(false)}>
|
|
확인
|
|
</Button>
|
|
</ModalFooter>
|
|
</ModalRoot>
|
|
</>
|
|
)
|
|
},
|
|
}
|
|
|
|
export const ConfirmDialog: Story = {
|
|
render: function Render() {
|
|
const [isOpen, setIsOpen] = useState(false)
|
|
return (
|
|
<>
|
|
<Button color="primary" onClick={() => setIsOpen(true)}>삭제하기</Button>
|
|
<ModalRoot isOpen={isOpen} onOpenChange={setIsOpen} className="w-75">
|
|
<ModalBody className="px-7.5 py-8">
|
|
<p className="text-sm text-dabeeo-black-34 font-medium text-center">
|
|
정말 삭제하시겠습니까?
|
|
</p>
|
|
</ModalBody>
|
|
<ModalFooter>
|
|
<Button color="gray" size="large" onClick={() => setIsOpen(false)}>
|
|
취소
|
|
</Button>
|
|
<Button color="primary" size="large" onClick={() => setIsOpen(false)}>
|
|
삭제
|
|
</Button>
|
|
</ModalFooter>
|
|
</ModalRoot>
|
|
</>
|
|
)
|
|
},
|
|
}
|