Files
HMDesign/src/components/story-page.tsx
T
shkim4 9394050c72 feat(storybook): add shared SW notice and refine SW previews
- Add StoryNotice and a withSWNotice decorator so every visible SW Story
  shows the common notice above its title; non-SW Stories are unaffected.
- Align the SW Header overview with the common SW Story page layout, let the
  preview Stage fill the available width and keep inner scroll on narrow screens.
- Rename SW/Footer to SW/하단 명령어바 (sidebar title only, Story IDs fixed via
  id: "sw-footer"), drop the top SWHeader from its preview and lower the
  workspace height bounds by the removed 49px.
2026-11-09 19:23:17 +09:00

79 lines
3.9 KiB
TypeScript

import { createContext, type ReactNode } from "react"
import "./story-page.css"
// Storybook presentation only (not part of @hm-design/ui): the common frame of a representative Story page.
// Page → Header (title, description) → Sections (title, description, specimen). It never styles the component being reviewed.
// Inner and title follow Foundation / Color; the section header → content split follows Center Graphic / 교량.
// A Story using it sets `parameters.layout: "fullscreen"` so the page owns its inner padding.
// Lets StateBoard render its specimen labels one level below the section heading.
export const StorySectionContext = createContext(false)
export function StoryPage({ className, children }: { className?: string; children: ReactNode }) {
return <div className={className ? `sb-page ${className}` : "sb-page"}><div className="sb-page-inner">{children}</div></div>
}
// Representative (sidebar) Stories omit `kicker`: the sidebar path already names the category.
// Hidden verification Stories keep passing it so their page structure stays unchanged.
export function StoryPageHeader({ kicker, title, description }: { kicker?: string; title: string; description?: ReactNode }) {
return (
<header className="sb-page-header">
{kicker ? <p className="sb-page-kicker">{kicker}</p> : null}
<h1 className="sb-page-title">{title}</h1>
{description ? <p className="sb-page-description">{description}</p> : null}
</header>
)
}
// Notice row (icon + text) shown above a Story page title. Reusable by any Story group through a decorator
// (e.g. src/sw/sw-story-notice.tsx); nothing renders it unless a group opts in. It owns a page frame whose Inner is the
// same as StoryPage's, and cancels its own bottom gutter so the page title below stays where it was.
// Icon: Group 1171290812.svg (circle + "!"), colors via currentColor.
export function StoryNotice({ children }: { children: ReactNode }) {
return (
<div className="sb-page sb-page-notice" data-story-notice="">
<div className="sb-page-inner">
<p className="sb-notice">
<svg className="sb-notice-icon" width="20" height="20" viewBox="0 0 29 29" fill="none" aria-hidden="true" focusable="false">
<path d="M15.7415 6L15.5383 17.3984H13.3743L13.1711 6H15.7415ZM14.4602 22.1484C14.0279 22.1484 13.6581 21.9974 13.3508 21.6953C13.0435 21.388 12.8925 21.0182 12.8977 20.5859C12.8925 20.1589 13.0435 19.7943 13.3508 19.4922C13.6581 19.1849 14.0279 19.0312 14.4602 19.0312C14.8821 19.0312 15.2467 19.1849 15.554 19.4922C15.8612 19.7943 16.0175 20.1589 16.0227 20.5859C16.0175 20.8724 15.942 21.1354 15.7961 21.375C15.6555 21.6094 15.468 21.7969 15.2336 21.9375C14.9993 22.0781 14.7415 22.1484 14.4602 22.1484Z" fill="currentColor" />
<circle cx="14.5" cy="14.5" r="13.5" stroke="currentColor" strokeWidth="2" />
</svg>
<span className="sb-notice-text">{children}</span>
</p>
</div>
</div>
)
}
// Headings and specimens share StoryPage's single Inner. Wide specimens own their local scroll frame.
export function StorySection({
title,
description,
id,
children,
}: {
title: string
description?: ReactNode
id?: string
children: ReactNode
}) {
return (
<section className="sb-page-section" id={id} aria-label={title}>
<header className="sb-page-section-header">
<h2 className="sb-page-section-title">{title}</h2>
{description ? <p className="sb-page-section-description">{description}</p> : null}
</header>
<StorySectionContext.Provider value>
<div className="sb-page-section-body">{children}</div>
</StorySectionContext.Provider>
</section>
)
}
export const STORY_KICKER = {
foundation: "HM DESIGN SYSTEM / FOUNDATION",
components: "HM DESIGN SYSTEM / COMPONENTS",
patterns: "HM DESIGN SYSTEM / PATTERNS",
center: "HM DESIGN SYSTEM / CENTER GRAPHIC",
} as const