Files
HMDesign/src/components/dropdown-menu.stories.tsx
T
shkim4 da0e647b49 docs(storybook): simplify sidebar Story pages around the UI
Drop the category kicker from the 83 sidebar Stories (kicker is now optional;
hidden verification Stories keep it) and shorten or remove repeated, obvious
or internal page/section descriptions. Required specs, limits, virtual-data
and undecided-value notices stay. Story IDs, exports, fixtures, shared state
notes and package code are unchanged. Record: docs/reports/storybook-ui-simplification-2026-10-22.md
2026-10-22 16:13:58 +09:00

107 lines
4.1 KiB
TypeScript

import { useState } from "react"
import type { Meta, StoryObj } from "@storybook/react-vite"
import {
Button,
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@hm-design/ui"
import { StoryPage, StoryPageHeader, StorySection } from "@/components/story-page"
// Dropdown Menu is a Radix overlay (Portal), so the representative Story is a trigger that opens the real menu, the same way as
// Dialog. The verification Story starts open. Radix owns keyboard navigation, focus return and Escape.
function Full({ defaultOpen }: { defaultOpen?: boolean }) {
const [showStatus, setShowStatus] = useState(true)
const [showPanel, setShowPanel] = useState(false)
const [position, setPosition] = useState("bottom")
return (
<DropdownMenu defaultOpen={defaultOpen}>
<DropdownMenuTrigger asChild>
<Button variant="primary" appearance="outline">
메뉴 열기
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56" align="start">
<DropdownMenuLabel>내 계정</DropdownMenuLabel>
<DropdownMenuGroup>
<DropdownMenuItem>
프로필 <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
설정 <DropdownMenuShortcut>⌘,</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem disabled>결제 (사용 불가)</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuLabel>보기</DropdownMenuLabel>
<DropdownMenuCheckboxItem checked={showStatus} onCheckedChange={setShowStatus}>
상태 표시줄
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem checked={showPanel} onCheckedChange={setShowPanel}>
패널
</DropdownMenuCheckboxItem>
<DropdownMenuSeparator />
<DropdownMenuLabel>위치</DropdownMenuLabel>
<DropdownMenuRadioGroup value={position} onValueChange={setPosition}>
<DropdownMenuRadioItem value="top">상단</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="bottom">하단</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="right">오른쪽</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
<DropdownMenuSeparator />
<DropdownMenuSub>
<DropdownMenuSubTrigger>더 보기</DropdownMenuSubTrigger>
<DropdownMenuSubContent>
<DropdownMenuItem>이메일로 공유</DropdownMenuItem>
<DropdownMenuItem>링크 복사</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuSub>
<DropdownMenuSeparator />
<DropdownMenuItem variant="destructive">로그아웃</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
}
const meta = { title: "Components/Overlay/Dropdown Menu", component: DropdownMenu, parameters: { layout: "centered" } } satisfies Meta<typeof DropdownMenu>
export default meta
type Story = StoryObj<typeof meta>
// Representative Story: the trigger opens the full menu (item, disabled, separator, checkbox, radio group, sub menu, destructive).
export const All: Story = {
name: "Dropdown Menu",
parameters: { layout: "fullscreen", controls: { disable: true } },
render: () => (
<StoryPage>
<StoryPageHeader
title="Dropdown Menu"
/>
<StorySection title="Overview" description="항목 · Disabled · 구분선 · Checkbox · Radio · 하위 메뉴 · 위험 항목">
<Full />
</StorySection>
</StoryPage>
),
}
// Verification Story: the same menu starting open, hidden from the sidebar (tag `verification`).
export const Open: Story = {
tags: ["verification"],
parameters: { layout: "fullscreen" },
render: () => (
<div className="flex min-h-[560px] justify-center p-8">
<Full defaultOpen />
</div>
),
}