Files
HMDesign/src/components/story-page.tsx
T
shkim4 63b3ab010b refactor(storybook): hide page headers and preserve accessibility
StoryPageHeader no longer shows the page title, kicker, description or the SW group notice; it renders only a visually hidden H1 with the Story title, so the preview keeps a page heading for screen readers while the first section starts at the top gutter (unchanged position).

- OrgChart verify-p8 / p9 / p9-1 / p9-2-composition wait for the first visible StoryPage content block and read the page H1 instead of .sb-page-title; existing expectations are unchanged.
- SW overview browser test clicks the page gutter as its outside-click target.
- Drop the unused .sb-page-description from the SW Storybook hide rules.
- Update the Storybook page frame rule in the project guideline.
2026-11-11 15:50:39 +09:00

67 lines
3.2 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 → Sections (title, description, specimen). It never styles the component being reviewed.
// Inner follows 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>
}
// Group notice context. Still provided by src/sw/sw-story-notice.tsx, but nothing renders it since the page header was
// removed from the Storybook frame (2026-11-11).
export const StoryNoticeContext = createContext<ReactNode>(null)
// 2026-11-11 (user request): the Storybook page header (kicker, description and group notice) is no longer shown, so every
// page visually starts with its first section. Only the title stays, as a visually hidden H1 (no box, no space), so the
// preview document keeps one page heading above its H2 sections: the preview's own document title is the Story ID and the
// iframe title is generic, so this is the only place a screen reader can identify the page.
// Stories keep their calls and props, so the visible header can be restored here.
// The product Page Header component (@hm-design/ui PageHeader) is unrelated and unchanged.
export function StoryPageHeader({ title }: { kicker?: string; title: string; description?: ReactNode }) {
return <h1 className="sb-page-a11y-title">{title}</h1>
}
// 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>
)
}
// Sections side by side (e.g. two charts per row). The grid owns the row gap (the section gap), so rows line up the same
// way as stacked sections; columns and alignment come from `className`.
export function StorySectionGrid({ className, children }: { className?: string; children: ReactNode }) {
return <div className={className ? `sb-page-section-grid ${className}` : "sb-page-section-grid"}>{children}</div>
}
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