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.
88 lines
3.4 KiB
TypeScript
88 lines
3.4 KiB
TypeScript
import { useId, type ReactNode } from "react"
|
||
import type { Meta, StoryObj } from "@storybook/react-vite"
|
||
import { Label, Switch } from "@hm-design/ui"
|
||
import { StateBoard } from "@/components/story-board"
|
||
import { StoryPage, StoryPageHeader, StorySection } from "@/components/story-page"
|
||
|
||
function Option({ label, children }: { label: string; children: (id: string) => ReactNode }) {
|
||
const id = useId()
|
||
return (
|
||
<div className="flex items-center gap-2">
|
||
{children(id)}
|
||
<Label htmlFor={id}>{label}</Label>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
const meta = {
|
||
title: "Components/Form/Switch",
|
||
component: Switch,
|
||
parameters: {
|
||
layout: "padded",
|
||
docs: {
|
||
description: {
|
||
component:
|
||
"현재 HM 규격: 트랙 36×20, 썸 16, On은 state-active, Off는 stroke 색. ui-viz에는 Switch 규격이 없어 참고만 했습니다. Radix Switch의 role=switch, 키보드, 접근성과 shadcn 기본 transition을 유지합니다.",
|
||
},
|
||
},
|
||
},
|
||
} satisfies Meta<typeof Switch>
|
||
export default meta
|
||
type Story = StoryObj<typeof meta>
|
||
|
||
export const All: Story = {
|
||
name: "Switch",
|
||
parameters: { layout: "fullscreen", controls: { disable: true } },
|
||
render: () => (
|
||
<StoryPage>
|
||
<StoryPageHeader title="Switch" />
|
||
<StorySection title="Overview">
|
||
<StateBoard
|
||
min={240}
|
||
states={[
|
||
{ id: "off", label: "Off", children: <Option label="Option">{(id) => <Switch id={id} />}</Option> },
|
||
{ id: "on", label: "On", children: <Option label="Option">{(id) => <Switch id={id} defaultChecked />}</Option> },
|
||
]}
|
||
/>
|
||
</StorySection>
|
||
<StorySection title="States">
|
||
<StateBoard
|
||
min={240}
|
||
states={[
|
||
{
|
||
id: "hover",
|
||
label: "Hover",
|
||
// data-sb-hover pins :hover (Storybook only, .storybook/pseudo-states.ts).
|
||
children: (
|
||
<div className="grid gap-3">
|
||
<Option label="Off">{(id) => <Switch id={id} data-sb-hover="" />}</Option>
|
||
<Option label="On">{(id) => <Switch id={id} defaultChecked data-sb-hover="" />}</Option>
|
||
</div>
|
||
),
|
||
},
|
||
{ id: "focus", label: "Focus", children: <Option label="Option">{(id) => <Switch id={id} />}</Option> },
|
||
{
|
||
id: "disabled",
|
||
label: "Disabled",
|
||
children: (
|
||
<div className="grid gap-3">
|
||
<Option label="Off">{(id) => <Switch id={id} disabled />}</Option>
|
||
<Option label="On">{(id) => <Switch id={id} disabled defaultChecked />}</Option>
|
||
</div>
|
||
),
|
||
},
|
||
]}
|
||
/>
|
||
</StorySection>
|
||
</StoryPage>
|
||
),
|
||
play: async ({ canvasElement }) => {
|
||
// preventScroll: the page opens at its header, not at the States section.
|
||
canvasElement.querySelector<HTMLButtonElement>('[data-overview-state="focus"] [role="switch"]')?.focus({ preventScroll: true })
|
||
},
|
||
}
|
||
|
||
export const Off: Story = { tags: ["verification"], render: () => <Option label="Option">{(id) => <Switch id={id} />}</Option> }
|
||
export const On: Story = { tags: ["verification"], render: () => <Option label="Option">{(id) => <Switch id={id} defaultChecked />}</Option> }
|
||
export const Disabled: Story = { tags: ["verification"], render: () => <Option label="Option">{(id) => <Switch id={id} disabled defaultChecked />}</Option> }
|