Design System / 07.4
Layout
Primitives for page rhythm, responsive shells, sticky sequences, product framing, and content grids.
Stack
The flex layout primitive that keeps spacing on the system scale, from the 3px mosaic gutter to the viewport-relative section rhythm tiers. It spaces children and does nothing else.
Live specimen
Rendered output
Column, gap="sm"
Small gap.
Shared rhythm.
Source order.
Row, baseline, justify="between"
API reference
Inputs, types, and behavior
- Inputgap
- TypeStackGap = "md"
- Behaviornone | flush (3px mosaic) | xs | sm | md | lg | rhythm-sm/md/lg (viewport-relative section tiers).
- Inputdirection
- Type"column" | "row"
- BehaviorDefault "column".
- Inputalign / justify
- Typestring
- BehaviorWord values mapped to static utilities (start, center, between, …).
- Inputas / wrap
- TypeElementType / boolean
- BehaviorSwap the element ("section", "ul", …); wrap enables flex-wrap. No padding or margin props by design.
Sticky stack
Chaptered sections that pin and stack as you scroll. Each sticky panel slides over the last at an escalating z-index, with a hairline top rule. Pure CSS positioning — no script.
Live specimen
Rendered output
Structure
Sections pin in source order with an escalating stacking level.
Spacing
Each panel keeps its own content rhythm and hairline boundary.
Source order
The same document sequence remains readable without sticky support.
API reference
Inputs, types, and behavior
- Inputtop
- Typenumber = 0
- BehaviorShared sticky offset in px — set it to your fixed-nav height.
- Inputchildren
- TypeStickyStackSection[]
- BehaviorSections receive escalating z-index; per-section top (number = 0) / zIndex (number = index + 1) props win.
- InputclassName
- Typestring?
- BehaviorMerged onto the StickyStack root element.
- InputclassName (section)
- Typestring?
- BehaviorSections default to min-h-[70svh] paper — override height and padding here.
Sticky scroll
A pinned panel synced to scrolling steps. The steps column scrolls past while one panel stays fixed, crossfading its media as each step’s band reaches viewport centre. Scroll this section to drive it. Below md the panel unpins and each step’s media renders inline. The active step is derived from scroll position, so it stays correct under reduced motion — a content swap, not an animation.
Live specimen
Rendered output
Supplied media

Scroll position

Text fallback
API reference
Inputs, types, and behavior
- Inputsteps
- Type{ title, content, media? }[]
- BehaviorThe pinned panel shows media; a step with no media falls back to its title set large.
- InputmediaSide
- Type"left" | "right"
- BehaviorSide the pinned panel occupies at md+, default "right".
- Inputtop
- Typenumber = 0
- BehaviorSticky top offset in px for the pinned panel — pass your header height.
- InputheadingAs
- Type"h2" | "h3" | "h4"
- BehaviorStep-title heading level. Default "h3".
- InputclassName
- Typestring?
- BehaviorMerged onto the outer grid.
Split landing shell
A page-scale split with a persistent lead rail and a longer detail column. The lead pins at lg, then returns to ordinary source order on smaller screens. It owns only the split, seam, and sticky geometry; the host supplies headings, navigation, actions, and supporting content.
Live specimen
Rendered output
Product thesis
Source package contract
The short proposition remains in view while the reader tests it against complete product surfaces.
01
Readme
State the contract in a measured text column.
02
Detail matrix
Pair each claim with a working example.
03
Working surface
Show the actual interface, not a generic illustration.
API reference
Inputs, types, and behavior
- Inputlead / children
- TypeReactNode / ReactNode
- BehaviorLead rail first in source order; children form the independent detail column.
- InputstickyTop
- Typenumber = 0
- BehaviorNon-negative desktop offset in px for a host-owned fixed header.
- InputleadClassName / contentClassName
- Typestring? / string?
- BehaviorMerged last onto the sticky lead wrapper and detail column.
- InputclassName
- Typestring?
- BehaviorMerged last onto the two-column root.
Detail showcase
A single-select accordion of titled rows with a synced media panel. Exactly one row is open at a time, and the panel shows that row’s media. It follows the disclosure-set keyboard model: Tab reaches every header, Up/Down/Home/End move focus, and Enter/Space activate. The panel media is illustrative only; below md it renders inline in the open row instead. Disclosure contents settle in 300ms and retreat in 180ms; the pinned media crossfades more slowly.
Live specimen
Rendered output

API reference
Inputs, types, and behavior
- Inputitems
- Type{ title, content, media? }[]
- BehaviorExactly one open at a time; the synced panel shows the active media (title fallback when absent).
- InputdefaultIndex
- Typenumber = 0
- BehaviorRow open on mount, with an out-of-range clamp.
- InputmediaSide
- Type"left" | "right"
- BehaviorSide the media panel occupies at md+, default "right".
- InputheadingAs
- Type"h2" | "h3" | "h4"
- BehaviorItem-title heading level. Default "h3".
- InputclassName
- Typestring?
- BehaviorMerged onto the outer grid.
Section
The foundational band: a full-bleed register wrapping a centered measure. Vertical space rides the rhythm tokens; the horizontal gutter follows --gutter-fluid and the display safe area. invert flips the band to the dark register edge to edge — a static swap, not the scroll-driven SectionInvert.
Live specimen
Rendered output
width="prose" · rhythm="sm"
A prose measure caps the line near 68ch so long-form copy stays legible. The band paints paper by default.
invert · dark register
The same band with invert — ink fills bleed-to-bleed so it punctuates the page as a dark register.
API reference
Inputs, types, and behavior
- Inputrhythm
- Type"sm" | "md" | "lg"
- BehaviorVertical padding tier off the viewport-relative --rhythm-* tokens. Default "md".
- Inputwidth
- Type"prose" | "default" | "wide" | "full"
- BehaviorMeasure of the centered container: prose 68ch, default 1200px, wide 1440px, full edge-to-edge.
- Inputinvert
- Typeboolean
- BehaviorFlips the band to the dark register via .dark-section. Static swap.
- Inputgutter
- Typeboolean
- BehaviorDefault true; adds the fluid horizontal gutter with safe-area insets. Set false for a flush container.
- Inputas
- Type"section" | "div"
- BehaviorRendered tag, default "section".
- Inputid / className
- Typestring?
- Behaviorid lands on the band; className merges onto it.
Section heading
The house section heading: a mono eyebrow, a fluid title, an optional lede dek, and a trailing action. When start-aligned, the action baselines against the title from md up and stacks below on mobile; when centered, it stacks along the same axis.
Live specimen
Rendered output
Selected work
Projects, 2021—2024
A slot-based heading that pairs a mono eyebrow with a fluid title and an optional supporting line.
Studio
What we make
API reference
Inputs, types, and behavior
- Inputtitle
- TypeReactNode
- BehaviorPlain text renders at the fluid title tier; a display component carries its own scale.
- Inputeyebrow
- TypeReactNode?
- BehaviorMono micro-label above the title.
- Inputdek
- TypeReactNode?
- BehaviorLede paragraph on --fluid-lede, dimmed, capped near 68ch.
- Inputaction
- TypeReactNode?
- BehaviorTrailing slot — baselines against the title (start) or stacks below (center).
- Inputalign
- Type"start" | "center"
- BehaviorDefault "start".
- Inputas
- Type"h2" | "h3"
- BehaviorHeading level and its fluid size tier. Default "h2".
- InputclassName
- Typestring?
- BehaviorMerged onto the wrapper.
Feature grid
Editorial feature grid on paper. divided (default) lets cells draw shared 1px top/left rules while an overflow clip removes the perimeter, so ragged rows keep no empty painted tracks. Feed items for the data API or compose your own cells as children; an item with href makes the whole cell a self-dimming link.
Live specimen
Rendered output
Systems
Identity
API reference
Inputs, types, and behavior
- Inputitems
- Type{ title, body?, icon?, href? }[]
- BehaviorData API. href turns the cell into a self-dimming link. Ignored when children are supplied.
- Inputchildren
- TypeReactNode?
- BehaviorCompose cells directly; takes precedence over items.
- Inputcolumns
- Type2 | 3 | 4
- BehaviorColumn count at md+ (4 steps through a 2-up at md). Default 3.
- Inputdivided
- Typeboolean
- BehaviorDefault true — hairline gutter separators. false gives discrete bordered cards.
- InputheadingAs
- Type"h2" | "h3" | "h4"
- BehaviorHeading level for data-api item titles. Default "h3".
- InputclassName
- Typestring?
- BehaviorMerged onto the grid.
Feature proof grid
A numbered feature matrix that pairs each claim with a compact example, diagram, metric, or interface fragment. Linked cells dim the full-ink title and settle their proof by one pixel; body and proof copy keep their specified contrast. Reduced motion keeps the proof still.
Live specimen
Rendered output
Explicit source
Measured contrast
API reference
Inputs, types, and behavior
- Inputitems
- TypeFeatureProofItem[]
- BehaviorEach item takes a title, optional body, proof, and safe href. Proof content may remain visible to assistive technology.
- Inputcolumns
- Type2 | 3 = 3
- BehaviorOne column on phones; three-column mode passes through two columns before xl.
- InputstartIndex / headingAs
- Typenumber = 1 / "h2" | "h3" | "h4"
- BehaviorNumbering is presentational; select a title level that follows the document outline.
- InputclassName
- Typestring?
- BehaviorMerged last onto the clipped grid root.
Product frame
A squared viewport for showing working product UI at useful scale. The frame provides compact title chrome, an optional navigation rail, a content slot, and a status footer. It does not invent browser dots, shadows, or product behavior; all controls and data remain host-owned.
Live specimen
Rendered output
Record
Sample
185 exports
API reference
Inputs, types, and behavior
- Inputtitle / meta / actions
- TypeReactNode / ReactNode? / ReactNode?
- BehaviorCompact frame header. The host owns any supplied controls and their behavior.
- Inputnavigation / navigationLabel
- TypeReactNode? / string
- BehaviorOptional responsive rail wrapped in a named nav landmark.
- Inputchildren / footer
- TypeReactNode / ReactNode?
- BehaviorThe product surface and an optional status line.
- InputcontentClassName / className
- Typestring? / string?
- BehaviorMerged last onto the content area and outer frame.
Feature row
Alternating split feature row: a copy column beside a media column, two-up at md+ and stacked (media after copy) below. reverse swaps the columns at md+ for zig-zag layouts while source order stays copy-first, so the reading order holds regardless of the flip. Squared media frame, hairline edge, no shadow.
Live specimen
Rendered output
Source-order composition
Reversed desktop tracks
API reference
Inputs, types, and behavior
- Inputtitle / body
- TypeReactNode
- BehaviorDisplay-register title beside body copy in the copy column.
- Inputmedia
- TypeReactNode
- BehaviorImage/video/any node for the framed media column.
- Inputreverse
- Typeboolean
- BehaviorDefault false; true puts media left at md+ for alternating rows (source order unchanged).
- Inputeyebrow / action
- TypeReactNode?
- BehaviorMono micro-label above the title; optional link/button below the body.
- Inputalign
- Type"center" | "start"
- BehaviorVertical alignment of copy against media at md+. Default "center".
- InputheadingAs
- Type"h2" | "h3" | "h4"
- BehaviorTitle heading level. Default "h2".
- InputclassName
- Typestring?
- BehaviorMerged onto the row grid.
Bento grid
Asymmetric mosaic on paper, composed with BentoCell. Column count rides a CSS variable so the grid holds at one column below md (spans suppressed) and opens to columns equal tracks at md+. Standalone cells own a hairline frame; flush and hairline grids suppress those frames so each shared seam is drawn once. Add href to make one a self-dimming link.
Live specimen
Rendered output
Case study
Atlas — a wayfinding system
colSpan=2 · rowSpan=2 — a wide feature tile leading the mosaic.
Discipline
Type
Linked
Journal
Practice
Working in monochrome
API reference
Inputs, types, and behavior
- InputBentoGrid.columns
- Typenumber
- BehaviorTrack count at md+; collapses to one column below. Default 3.
- InputBentoGrid.gap
- Type"flush" | "hairline" | "normal"
- BehaviorGutter: flush is an unframed 3px mosaic gap; hairline draws one shared seam; normal separates individually framed cells. Default "normal".
- InputBentoCell.colSpan / rowSpan
- Typenumber
- BehaviorTrack / row span at md+ (default 1); ignored on mobile where every cell is full width.
- InputBentoCell.href
- Typestring?
- BehaviorMakes the tile a self-dimming link.
- InputclassName
- Typestring?
- BehaviorMerged onto the grid or cell.
App shell
The product frame: a fixed left rail with a layout-safe, instant expanded ↔ icon-only width swap; its contents recede and settle through opacity and a four-pixel translation. A sticky topbar sits over the scrolling content region. Below md the rail folds into an off-canvas paper dialog with a labelled close control, background inertness, scroll-lock, Escape, focus containment, and trigger restoration. Pair it with SidebarNav, which takes flat items and grouped sections of rows carrying icon, badge and active state — the shell injects collapsed for you.
Live specimen
Rendered output
A fixed left rail collapses to an icon-only strip on the topbar toggle, and folds to an off-canvas drawer below the md breakpoint. The Overview panel renders here.
Boxed specimen: AppShell is a page-level frame (min-h-dvh), constrained to 520px with overflow-hidden so it stays inside the docs layout.
API reference
Inputs, types, and behavior
- Inputsidebar
- TypeReactNode
- BehaviorA direct SidebarNav element (or any node). The current collapsed flag is cloned onto a direct element automatically.
- Inputtopbar
- TypeReactNode?
- BehaviorStrip across the head of the content region, beside the collapse / MENU controls.
- Inputchildren
- TypeReactNode
- BehaviorThe scrolling content column.
- Inputcollapsed / onCollapsedChange
- Typeboolean / (c) => void
- BehaviorControlled rail collapse. The rail exposes its state as data-rail="collapsed|expanded" on the aside, so a host can swap a lockup or hide a label without measuring the rail's width.
- Inputscroll margin
- Type—
- BehaviorThe content column sets scroll-margin-block-start for anchors and focus targets so they clear the sticky topbar. Hosts need not measure the header.
- InputdefaultCollapsed
- Typeboolean
- BehaviorUncontrolled initial collapse. Default false.
- InputcontentAs
- Type"main" | "div"
- BehaviorDefault "main" supplies the page landmark. Use "div" only when embedding the shell inside an existing main, as this specimen does.
- InputclassName
- Typestring?
- BehaviorMerged onto the root frame (min-h-screen + min-h-dvh) — how the specimen above is boxed to a fixed height.
Page header
A page masthead for the content region: an optional breadcrumb rung, the title carrying an action cluster on the same baseline (md+; it drops below on phones), a dimmed lede, and an optional tab row seated on a hairline. Presentational — slots only.
Live specimen
Rendered output
Invoices
Every invoice raised this quarter, with status and totals.
API reference
Inputs, types, and behavior
- Inputtitle
- TypeReactNode
- BehaviorPage title, set at --fluid-h2.
- InputheadingAs
- Type"h1" | "h2" | "h3"
- BehaviorTitle heading level. Default "h1"; this embedded specimen uses h3 beneath the section h2.
- Inputactions
- TypeReactNode?
- BehaviorRight-aligned button cluster, baseline with the title on md+.
- Inputbreadcrumb
- TypeReactNode?
- BehaviorA Breadcrumbs slot rendered above the title.
- Inputdescription
- TypeReactNode?
- BehaviorDimmed lede under the title.
- Inputtabs
- TypeReactNode?
- BehaviorAn underline tab-nav row seated on a hairline bottom rule.
- InputclassName
- Typestring?
- BehaviorMerged onto the root column.
Section invert
Scroll-driven inversion with an instant threshold swap. The previous scrubbed color interpolation animated non-compositor properties and passed through low-contrast midpoint colors; both retained mode values now use the same discrete, motion-safe change. Scroll events are captured, so nested overflow containers drive it too. Interior rules should use currentColor so they invert in step.
Live specimen
Rendered output
Inverted section
The hairline above changes register in step because it inherits currentColor.
API reference
Inputs, types, and behavior
- Inputmode
- Type"scrub" | "threshold"
- BehaviorCompatibility selector. Both values now perform the same instant threshold swap; default remains "scrub" so existing callers keep type compatibility.
- Inputstart / end
- Typenumber = 0.9 / 0.75
- BehaviorViewport-height band fractions (useScrollProgress semantics) — tune per section height.
- Inputthreshold
- Typenumber = 0.5
- BehaviorProgress at which the register flips in either mode.
- InputclassName
- Typestring?
- BehaviorMerged onto the root element.