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.
99 lines
3.7 KiB
TypeScript
99 lines
3.7 KiB
TypeScript
import type { Meta, StoryObj } from "@storybook/react-vite"
|
|
import { Avatar, AvatarFallback, AvatarImage } from "@hm-design/ui"
|
|
import { StateBoard } from "@/components/story-board"
|
|
import { StoryPage, StoryPageHeader, StorySection } from "@/components/story-page"
|
|
|
|
// Images are inline data URIs so the Story does not depend on the network. "Broken" uses an address that cannot load so the
|
|
// Radix fallback shows. Radix renders the image only after it loads.
|
|
|
|
const photo =
|
|
"data:image/svg+xml;utf8," +
|
|
encodeURIComponent(
|
|
'<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80"><rect width="80" height="80" fill="#266651"/><circle cx="40" cy="31" r="14" fill="#bddfd4"/><rect x="14" y="50" width="52" height="40" rx="22" fill="#bddfd4"/></svg>'
|
|
)
|
|
|
|
function Sizes() {
|
|
return (
|
|
<div className="flex items-end gap-4">
|
|
{(["sm", "default", "lg"] as const).map((size) => (
|
|
<div key={size} className="grid justify-items-center gap-2">
|
|
<Avatar size={size}>
|
|
<AvatarImage src={photo} alt="" />
|
|
<AvatarFallback>한맥</AvatarFallback>
|
|
</Avatar>
|
|
<span className="text-xs text-muted-foreground">{size}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
// `showCaption={false}` drops the captions on the representative page (they restate the visible fallback text); the verification Story keeps them.
|
|
function Fallbacks({ showCaption = true }: { showCaption?: boolean }) {
|
|
const items = [
|
|
{ label: "한글 두 글자", text: "김한" },
|
|
{ label: "영문 두 글자", text: "HM" },
|
|
{ label: "한 글자", text: "한" },
|
|
{ label: "긴 fallback", text: "ABCDEFGHIJ" },
|
|
]
|
|
return (
|
|
<div className="flex flex-wrap items-end gap-4">
|
|
{items.map((i) => (
|
|
<div key={i.label} className="grid justify-items-center gap-2">
|
|
<Avatar>
|
|
<AvatarImage src="/broken-avatar-image.png" alt="" />
|
|
<AvatarFallback>{i.text}</AvatarFallback>
|
|
</Avatar>
|
|
{showCaption ? <span className="text-xs text-muted-foreground">{i.label}</span> : null}
|
|
</div>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function Group() {
|
|
return (
|
|
<div className="flex items-center gap-3">
|
|
<Avatar>
|
|
<AvatarImage src={photo} alt="김한맥" />
|
|
<AvatarFallback>김한</AvatarFallback>
|
|
</Avatar>
|
|
<div className="grid text-sm">
|
|
<span className="font-medium">김한맥</span>
|
|
<span className="text-muted-foreground">노선 설계팀</span>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const sections = [
|
|
{ id: "image", label: "Image", node: <Sizes /> },
|
|
{ id: "fallback", label: "Fallback", node: <Fallbacks showCaption={false} /> },
|
|
{ id: "composition", label: "Composition", node: <Group /> },
|
|
]
|
|
|
|
const meta = { title: "Components/Data & Display/Avatar", component: Avatar, parameters: { layout: "padded" } } satisfies Meta<typeof Avatar>
|
|
export default meta
|
|
type Story = StoryObj<typeof meta>
|
|
|
|
const board = (...ids: string[]) => (
|
|
<StateBoard min={320} states={sections.filter((s) => ids.includes(s.id)).map((s) => ({ id: s.id, label: s.label, children: s.node }))} />
|
|
)
|
|
|
|
// Representative Story: the common Story page; the sections group the same specimens.
|
|
export const All: Story = {
|
|
name: "Avatar",
|
|
parameters: { layout: "fullscreen", controls: { disable: true } },
|
|
render: () => (
|
|
<StoryPage>
|
|
<StoryPageHeader title="Avatar" />
|
|
<StorySection title="Overview">{board("image")}</StorySection>
|
|
<StorySection title="States">{board("fallback")}</StorySection>
|
|
<StorySection title="Usage">{board("composition")}</StorySection>
|
|
</StoryPage>
|
|
),
|
|
}
|
|
|
|
export const Image: Story = { tags: ["verification"], render: () => <Sizes /> }
|
|
export const FallbackError: Story = { tags: ["verification"], name: "Fallback", render: () => <Fallbacks /> }
|