style(storybook): unify content hierarchy and section spacing
- Story page frame: H2 16/24/700 -> 12px -> divider -> 16px -> content, sections 28px apart;
StorySectionGrid keeps its 24px column gap
- Content indent (--sb-page-indent 16px, 12px at 640px and below): .sb-page-indent for information
blocks; group boards (StateBoard / CardBoard, data-sb-board) indented once per section block so
per-column boards keep their 24px gap
- Input / Select / Toggle Sizes grids take the same indent; field Labels unchanged
- Full-width Pattern previews (GNB, LNB, Loading Screen, Page Header) opt out with indent={false}
- Foundation/폰트: Text Colors name / usage / HEX levels, Font Family and Font Weight token lines,
Specimens row spacing and indent; specimen values unchanged
- Guideline and WORKING_CONTEXT updated
This commit is contained in:
1 parent
15c64b0003
commit
3e97cd0b2d
14 files changed
+89
-30
No files matched your search
@@ -36,9 +36,10 @@ function Specimen({ surface = "surface", action, title = "프로젝트 정보",
|
||||
|
||||
// Story-only equal-column board for this page: 3 columns on PC, 2 / 1 on narrower widths. Variants and Usage share it,
|
||||
// so a Usage cell has the same width as one Variants cell. Label markup/colors match StateBoard (shared component untouched).
|
||||
// `data-sb-board` gives it the same common group indent as StateBoard (story-page.css).
|
||||
function CardBoard({ states }: { states: BoardState[] }) {
|
||||
return (
|
||||
<div className="grid grid-cols-1 items-start gap-x-6 gap-y-8 min-[640px]:grid-cols-2 min-[900px]:grid-cols-3">
|
||||
<div data-sb-board="" className="grid grid-cols-1 items-start gap-x-6 gap-y-8 min-[640px]:grid-cols-2 min-[900px]:grid-cols-3">
|
||||
{states.map(({ id, label, children }) => (
|
||||
<section className="grid min-w-0 content-start gap-3" key={id} data-overview-state={id} aria-label={label}>
|
||||
<header className="grid gap-2 border-b border-black/10 pb-2">
|
||||
|
||||
@@ -134,7 +134,10 @@ export const All: Story = {
|
||||
<StoryPage>
|
||||
<StoryPageHeader title="Input" />
|
||||
<StorySection title="Sizes">
|
||||
<SizeComparison showSpec={false} />
|
||||
{/* Same common indent as the group boards below; Small / Medium / Large stay the fields' own Labels. */}
|
||||
<div className="sb-page-indent">
|
||||
<SizeComparison showSpec={false} />
|
||||
</div>
|
||||
</StorySection>
|
||||
<StorySection title="States">
|
||||
<StateBoard
|
||||
|
||||
@@ -176,8 +176,9 @@ export const All: Story = {
|
||||
<StoryPage>
|
||||
<StoryPageHeader title="Select" />
|
||||
<StorySection title="Sizes">
|
||||
{/* Same 3-column track as States / Validation: Medium and Large take the first two columns, the third stays empty. */}
|
||||
<div className="grid items-start gap-6 [grid-template-columns:repeat(auto-fill,minmax(min(100%,240px),1fr))] min-[1000px]:grid-cols-3">
|
||||
{/* Same 3-column track as States / Validation: Medium and Large take the first two columns, the third stays empty.
|
||||
The grid takes the same common indent as the group boards (.sb-page-indent); Medium / Large stay field Labels. */}
|
||||
<div className="grid items-start gap-6 sb-page-indent [grid-template-columns:repeat(auto-fill,minmax(min(100%,240px),1fr))] min-[1000px]:grid-cols-3">
|
||||
{sizes.map((spec) => (
|
||||
<SizeCard key={spec.size} spec={spec} showSpec={false} />
|
||||
))}
|
||||
|
||||
@@ -11,12 +11,19 @@ export type BoardState = { id: string; label: string; note?: string; noteAfter?:
|
||||
// trigger need whole-pixel columns: a fractional column (e.g. 358.4px) puts the trigger edge between device pixels while the
|
||||
// popper rounds the popup to whole pixels, so the two outlines end up 1px apart.
|
||||
// The labels are H3 (14/20/500, secondary) under the section's divider: they carry no divider of their own, and rows sit
|
||||
// 24px apart (the section gap of story-page.css).
|
||||
export function StateBoard({ states, min = 320, fixed = false }: { states: BoardState[]; min?: number; fixed?: boolean }) {
|
||||
// 24px apart (one step tighter than the 28px section gap of story-page.css).
|
||||
// 2026-11-11: inside a StorySection the board is marked `data-sb-board`; story-page.css then indents, once, the block directly
|
||||
// under the section body that is or holds the board (16px / 12px at 640px and below, --sb-page-indent). Stories that put one
|
||||
// single-group board per column of their own grid therefore get one indent for the whole grid, not one per column, and keep
|
||||
// their 24px column gap. Section title (L1) → group label (L2) → specimen (L3). `indent={false}` leaves the mark off and keeps
|
||||
// the board on the section edge (full-width Pattern previews such as GNB / Page Header).
|
||||
export function StateBoard({ states, min = 320, fixed = false, indent = true }: { states: BoardState[]; min?: number; fixed?: boolean; indent?: boolean }) {
|
||||
// Inside a StorySection the labels sit one heading level below the section title.
|
||||
const Label = useContext(StorySectionContext) ? "h3" : "h2"
|
||||
const inSection = useContext(StorySectionContext)
|
||||
const Label = inSection ? "h3" : "h2"
|
||||
return (
|
||||
<div
|
||||
data-sb-board={inSection && indent ? "" : undefined}
|
||||
className={`grid items-start gap-x-6 gap-y-6 ${fixed ? "[grid-template-columns:repeat(auto-fill,min(100%,var(--sb-state-min,320px)))]" : "[grid-template-columns:repeat(auto-fill,minmax(min(100%,var(--sb-state-min,320px)),1fr))]"}`}
|
||||
style={{ "--sb-state-min": `${min}px` } as CSSProperties}
|
||||
>
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
/* Storybook presentation only. Common page frame for representative Stories; all selectors stay inside .sb-page.
|
||||
2026-11-11 compact document rhythm, shared by Web / Chart / OrgChart (SW and CENTER pages use the same frame only):
|
||||
2026-11-11: the H1 page title / description header is no longer shown (the H1 stays for screen readers only); pages start with the
|
||||
H2 section title 16/24/700 (body-md) over a thin divider → 12px → specimen; sections 24px apart (Dashboard gap);
|
||||
H3 specimen labels 14/20/500 secondary, no divider of their own (story-board.tsx). Top / bottom gutter 16–24px.
|
||||
H2 section title 16/24/700 (body-md) → 12px → thin divider → 16px → content; sections 28px apart (2026-11-11 rhythm, first applied
|
||||
on Foundation / 폰트); H3 specimen labels 14/20/500 secondary, no divider of their own (story-board.tsx). Top / bottom gutter 16–24px.
|
||||
Side margins are unchanged (16px up to 480px, growing to 60px at 768px): the SW breakpoints 2040 / 1125 / 787 depend on them.
|
||||
No design token is added; --sb-page-* only names existing component token values for this Storybook frame. */
|
||||
Only information blocks (text, spec tables) opt in to the content indent (.sb-page-indent); previews stay on the section edge,
|
||||
except group boards (H3 label + its specimens, marked data-sb-board by StateBoard / CardBoard), indented once per section block below.
|
||||
No design token is added; --sb-page-* only names this Storybook frame's values (component token values or plain px). */
|
||||
.sb-page {
|
||||
--sb-page-gutter: clamp(16px, 2vw, 24px);
|
||||
--sb-page-section-gap: 24px;
|
||||
--sb-page-section-gap: 28px;
|
||||
--sb-page-indent: 16px;
|
||||
--sb-page-section-title-font-size: var(--hm-dialog-body-font-size);
|
||||
--sb-page-section-title-line-height: var(--hm-dialog-body-line-height);
|
||||
box-sizing: border-box;
|
||||
@@ -46,8 +49,8 @@
|
||||
|
||||
.sb-page .sb-page-section { margin-top: var(--sb-page-section-gap); scroll-margin-top: 16px; }
|
||||
.sb-page .sb-page-section-header {
|
||||
padding-bottom: 8px;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 12px;
|
||||
margin-bottom: 16px;
|
||||
border-bottom: 1px solid var(--hm-sem-stroke-input-default);
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
@@ -65,7 +68,16 @@
|
||||
font-weight: var(--hm-input-font-weight);
|
||||
}
|
||||
.sb-page .sb-page-section-body { min-width: 0; }
|
||||
/* Opt-in content indent for information blocks under a section divider (title and divider stay on the edge). Put it on the block
|
||||
that holds the whole group (a grid, a table pair), not on single cells. Never on previews, bordered card grids or SW full-width examples. */
|
||||
.sb-page .sb-page-indent { padding-left: var(--sb-page-indent); }
|
||||
/* Group boards (StateBoard / CardBoard mark themselves data-sb-board): the same indent, applied once to the section body's direct
|
||||
child that is or holds a board, so a Story grid with one board per column is indented as a whole and keeps its column gap.
|
||||
Scoped to direct children of a section body; unmarked blocks (full-width Pattern previews, charts, canvases) are untouched. */
|
||||
.sb-page .sb-page-section-body > :is([data-sb-board], :has([data-sb-board])) { padding-left: var(--sb-page-indent); }
|
||||
@media (max-width: 640px) { .sb-page { --sb-page-indent: 12px; } }
|
||||
/* Sections side by side (StorySectionGrid): grid items keep their margins, so the grid owns the row gap instead.
|
||||
Only the row gap follows the section gap; the column gap stays 24px so side-by-side preview widths do not change.
|
||||
Columns and alignment stay with the Story (className): this unlayered rule would override Tailwind's layered grid-cols-*. */
|
||||
.sb-page .sb-page-section-grid { display: grid; gap: var(--sb-page-section-gap) 24px; margin-top: var(--sb-page-section-gap); }
|
||||
.sb-page .sb-page-section-grid > .sb-page-section { margin-top: 0; }
|
||||
@@ -40,7 +40,8 @@ function WithIcon() {
|
||||
function Sizes() {
|
||||
return (
|
||||
// 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">
|
||||
// Same common indent as the group boards of the page (.sb-page-indent).
|
||||
<div className="grid items-start gap-6 sb-page-indent [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>
|
||||
|
||||
Reference in new issue
Block a user