style(storybook): refine form component stories

This commit is contained in:
shkim4 committed 2026-11-09 15:33:23 +09:00
1 parent e47eb040f2
commit f6b92d781a
23 files changed
+471 -182

No files matched your search

+29 -9
View File
@@ -1,7 +1,7 @@
import type { Meta, StoryObj } from "@storybook/react-vite"
import { BoldIcon, ItalicIcon, StarIcon } from "lucide-react"
import { Toggle, ToggleGroup, ToggleGroupItem } from "@hm-design/ui"
import { StateBoard } from "@/components/story-board"
import { StateBoard, type BoardState } from "@/components/story-board"
import { StoryPage, StoryPageHeader, StorySection } from "@/components/story-page"
// Toggle is a persistent pressed-state control. The representative Story shows each state with real, clickable toggles; the same
@@ -39,7 +39,8 @@ function WithIcon() {
function Sizes() {
return (
<div className="grid gap-3">
// 3 equal columns on PC (iframe width 1000px and up): sm / default / lg; fewer columns below that (240px minimum).
<div className="grid items-start gap-6 [grid-template-columns:repeat(auto-fill,minmax(min(100%,240px),1fr))] min-[1000px]:grid-cols-3">
{(["sm", "default", "lg"] as const).map((size) => (
<div key={size} data-toggle-size={size} className="flex flex-wrap items-center gap-3">
<Toggle size={size} variant="outline" aria-label={`${size} icon-only`}><StarIcon /></Toggle>
@@ -71,21 +72,41 @@ const meta = { title: "Components/Form/Toggle", component: Toggle, parameters: {
export default meta
type Story = StoryObj<typeof meta>
const board = (...ids: string[]) => (
<StateBoard min={360} states={sections.filter((s) => ids.includes(s.id)).map((s) => ({ id: s.id, label: s.label, children: s.node }))} />
)
// Representative-page layout (Storybook presentation only). StateBoard's own auto-fill grid cannot give equal columns that
// fill a cell, so each specimen sits in its own single-column StateBoard (min larger than any column) inside a grid.
const specimen = (id: string): BoardState => {
const s = sections.find((section) => section.id === id)!
return { id: s.id, label: s.label, children: s.node }
}
function SpecimenGrid({ states }: { states: BoardState[] }) {
return (
<div className="grid items-start gap-6 [grid-template-columns:repeat(auto-fill,minmax(min(100%,240px),1fr))] min-[1000px]:grid-cols-3">
{states.map((state) => (
<StateBoard key={state.id} min={10000} states={[state]} />
))}
</div>
)
}
// Representative Story: the common Story page; the sections group the same specimens.
// Overview is renamed Variants. On PC (iframe width 1000px and up) Variants and States use the first two of the same 3 equal
// columns as the rows below, and the third column stays empty; below that they stack.
export const All: Story = {
name: "Toggle",
parameters: { layout: "fullscreen", controls: { disable: true } },
render: () => (
<StoryPage>
<StoryPageHeader title="Toggle" />
<StorySection title="Overview">{board("offon")}</StorySection>
<div className="grid gap-x-6 min-[1000px]:grid-cols-3">
<StorySection title="Variants">
<StateBoard min={10000} states={[specimen("offon")]} />
</StorySection>
<StorySection title="States">
<StateBoard min={10000} states={[specimen("disabled")]} />
</StorySection>
</div>
<StorySection title="단독 · 연결 그룹">
<StateBoard
min={360}
<SpecimenGrid
states={[
{ id: "single-toggle", label: "단독", children: <Toggle variant="outline">알림</Toggle> },
{ id: "group-single", label: "연결 그룹 · 단일 선택", children: <ToggleGroup type="single" variant="outline" defaultValue="left" aria-label="정렬"><ToggleGroupItem value="left">왼쪽</ToggleGroupItem><ToggleGroupItem value="center">가운데</ToggleGroupItem><ToggleGroupItem value="right">오른쪽</ToggleGroupItem></ToggleGroup> },
@@ -96,7 +117,6 @@ export const All: Story = {
<StorySection title="Sizes">
<Sizes />
</StorySection>
<StorySection title="States">{board("disabled")}</StorySection>
</StoryPage>
),
}