Files
HMDesign/src/components/radio-group.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

92 lines
3.8 KiB
TypeScript

import type { Meta, StoryObj } from "@storybook/react-vite"
import { Label, RadioGroup, RadioGroupItem } from "@hm-design/ui"
import { StateBoard } from "@/components/story-board"
import { StoryPage, StoryPageHeader, StorySection } from "@/components/story-page"
// Current HM Radio Group. ui-viz has no Radio spec, so it was reference only.
function Group({
prefix,
defaultValue = "a",
disabled,
disabledItem,
invalid,
orientation,
hoverItem,
}: {
prefix: string
defaultValue?: string
disabled?: boolean
disabledItem?: string
invalid?: boolean
orientation?: "horizontal" | "vertical"
// Pins :hover on one item with the Storybook-only data-sb-hover attribute (.storybook/pseudo-states.ts).
hoverItem?: string
}) {
return (
<RadioGroup defaultValue={defaultValue} disabled={disabled} orientation={orientation} aria-label={prefix}>
{["a", "b", "c"].map((v) => (
<div key={v} className="flex items-center gap-2">
<RadioGroupItem value={v} id={`${prefix}-${v}`} disabled={disabledItem === v} aria-invalid={invalid ? true : undefined} data-sb-hover={hoverItem === v ? "" : undefined} />
<Label htmlFor={`${prefix}-${v}`}>Option {v.toUpperCase()}</Label>
</div>
))}
</RadioGroup>
)
}
const meta = {
title: "Components/Form/Radio Group",
component: RadioGroup,
parameters: {
layout: "padded",
docs: {
description: {
component:
"현재 HM 규격: 18px 원, border 1px(stroke), Checked/Selected는 state-active 테두리 + 8px state-active dot, group gap 12(horizontal 16). Radix RadioGroup의 roving focus, 방향키 선택, ARIA를 유지합니다. ui-viz에는 Radio 규격이 없어 참고만 했습니다.",
},
},
},
} satisfies Meta<typeof RadioGroup>
export default meta
type Story = StoryObj<typeof meta>
export const All: Story = {
name: "Radio Group",
parameters: { layout: "fullscreen", controls: { disable: true } },
render: () => (
<StoryPage>
<StoryPageHeader title="Radio Group" />
<StorySection title="Overview">
<StateBoard min={240} states={[{ id: "vertical", label: "Vertical", children: <Group prefix="v" defaultValue="b" /> }]} />
</StorySection>
<StorySection title="Variants">
<StateBoard min={240} states={[{ id: "horizontal", label: "Horizontal", children: <Group prefix="h" orientation="horizontal" /> }]} />
</StorySection>
<StorySection title="States">
<StateBoard
min={240}
states={[
{ id: "hover", label: "Hover", children: <Group prefix="hv" defaultValue="" hoverItem="a" /> },
{ id: "focus", label: "Focus", children: <Group prefix="f" /> },
{ id: "disabled-item", label: "Disabled · 항목", children: <Group prefix="di" disabledItem="b" /> },
{ id: "disabled-group", label: "Disabled · 그룹", children: <Group prefix="dg" disabled /> },
]}
/>
</StorySection>
<StorySection title="Validation">
<StateBoard min={240} states={[{ id: "error", label: "Error", children: <Group prefix="e" invalid /> }]} />
</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="radio"][data-state="checked"]')?.focus({ preventScroll: true })
},
}
export const Vertical: Story = { tags: ["verification"], render: () => <Group prefix="sv" /> }
export const Horizontal: Story = { tags: ["verification"], render: () => <Group prefix="sh" orientation="horizontal" /> }
export const Disabled: Story = { tags: ["verification"], render: () => <Group prefix="sd" disabled /> }
export const Error: Story = { tags: ["verification"], render: () => <Group prefix="se" invalid /> }