Files
HMDesign/src/components/drawer.stories.tsx
T
shkim4 4c29894e56 refactor(storybook): simplify component and preview examples
Drop page / section descriptions, state notes and repeated captions from
the representative Stories of 44 components, the Patterns, Center
Graphic and OrgChart pages. Value readouts, spec lists and captions hide
only on the representative page; hidden verification Stories keep them.
Tabs Default API and the Filter Bar draft / applied counts move to the
hidden DefaultApi and DraftApplied Stories; Center Overview is hidden
with its direct URL kept. Story IDs are unchanged.

Align the component, pattern and OrgChart docs with the pages, point the
quality reference check at the DraftApplied Story, and make the P8
styles check expect no section header on the preview-only Expanded page.
2026-10-23 00:28:05 +09:00

120 lines
4.0 KiB
TypeScript

import type { Meta, StoryObj } from "@storybook/react-vite"
// Usage: preserved native label fixtures do not define a new-screen exception. Use public Label
// for supported fields (docs/components/label.md §5); copy only actions requested by the screen.
import { Button, Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger, Input } from "@hm-design/ui"
import { StoryPage, StoryPageHeader, StorySection } from "@/components/story-page"
// Drawer is a modal vaul overlay (Portal). The representative Story opens the real Drawer from its triggers; drag the handle or
// the panel down to dismiss. The same cases start open in the verification Stories. vaul owns the drag, Radix the focus and ARIA.
const longText = "긴 내용은 Body 영역만 세로로 scroll 하고 Header와 Footer는 그대로 보입니다. "
function Frame({
trigger,
defaultOpen,
title,
description,
children,
actions,
}: {
trigger: string
defaultOpen?: boolean
title: string
description?: string
children: React.ReactNode
actions?: React.ReactNode
}) {
return (
<Drawer defaultOpen={defaultOpen}>
<DrawerTrigger asChild>
<Button variant="primary" appearance="outline">
{trigger}
</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>{title}</DrawerTitle>
{description ? <DrawerDescription>{description}</DrawerDescription> : null}
</DrawerHeader>
<DrawerBody>{children}</DrawerBody>
<DrawerFooter>{actions}</DrawerFooter>
</DrawerContent>
</Drawer>
)
}
const actions = (
<>
<DrawerClose asChild>
<Button variant="cancel" appearance="solid">
취소
</Button>
</DrawerClose>
<DrawerClose asChild>
<Button variant="primary" appearance="solid">
실행
</Button>
</DrawerClose>
</>
)
function Basic({ defaultOpen }: { defaultOpen?: boolean }) {
return (
<Frame trigger="기본" defaultOpen={defaultOpen} title="작업 선택" description="아래에서 올라오는 패널입니다. 핸들을 아래로 끌어 닫을 수 있습니다." actions={actions}>
<p>짧은 내용은 내용 높이만큼만 차지합니다.</p>
</Frame>
)
}
function FormCase({ defaultOpen }: { defaultOpen?: boolean }) {
return (
<Frame trigger="폼" defaultOpen={defaultOpen} title="프로젝트 정보" actions={actions}>
<div className="grid gap-2">
<label htmlFor="drawer-form-name" className="text-sm font-medium text-muted-foreground">
프로젝트명
</label>
<Input id="drawer-form-name" size="medium" placeholder="프로젝트명을 입력하세요" />
</div>
</Frame>
)
}
function LongCase({ defaultOpen }: { defaultOpen?: boolean }) {
return (
<Frame trigger="긴 내용" defaultOpen={defaultOpen} title="긴 내용" description="Body만 scroll 합니다." actions={actions}>
{Array.from({ length: 30 }, (_, i) => (
<p key={i} className="mb-3">
{longText}
</p>
))}
</Frame>
)
}
const meta = { title: "Components/Overlay/Drawer", component: Drawer, parameters: { layout: "centered" } } satisfies Meta<typeof Drawer>
export default meta
type Story = StoryObj<typeof meta>
export const All: Story = {
name: "Drawer",
parameters: { layout: "fullscreen", controls: { disable: true } },
render: () => (
<StoryPage>
<StoryPageHeader title="Drawer" />
<StorySection title="Overview">
<Basic />
</StorySection>
<StorySection title="Usage">
<div className="flex flex-wrap gap-3">
<FormCase />
<LongCase />
</div>
</StorySection>
</StoryPage>
),
}
export const Open: Story = { tags: ["verification"], render: () => <Basic defaultOpen /> }
export const Form: Story = { tags: ["verification"], render: () => <FormCase defaultOpen /> }
export const LongContent: Story = { tags: ["verification"], name: "Long Content", render: () => <LongCase defaultOpen /> }