Layout primitives should make the page shape obvious before content arrives. Use Container and Section for the outer reading frame, Stack for ordered vertical rhythm, and Grid or Columns only when siblings are peers.
1. FrameContainer sets the readable width; Section names a related group.
2. FlowStack owns rhythm; Grid and Columns distribute peers without changing reading order.
3. SeparateDivider is a semantic break; Spacer is a rare explicit gap when composition cannot express it.
4. ShellSidebar and Splitter belong to app chrome or work surfaces, not ordinary document sections.
A box that reserves space at a fixed width:height ratio before its media loads, eliminating layout shift. The ratio is an enum drawn from a known design ladder (square, 4:3, 3:2, 16:9, 21:9) so embeds stay visually consistent and a one-off ratio cannot creep in. The single child is stretched to fill and object-fit cover is applied.
Readiness
complete
Preview
live
Props
1
Examples
3
Code
implementation mapped
When to use
Embedding a video or iframe that must not reflow on load
A media thumbnail grid where every tile must match
A responsive hero image with a locked cinematic ratio
Avatar or preview squares that must stay square at any width
When not to use
Text or content that should size to its own height — use a plain block
A box whose height is driven by its content — use Stack/Container
Charts that compute their own dimensions
Layouts needing different ratios per breakpoint (compose two instances)
Accessibility
Role: presentation
No keyboard shortcuts
Screen reader: Layout-only; AspectRatio adds no semantics. The embedded media is responsible for its own alt text, title, or accessible name.
Notes: Always give the contained image an alt attribute and the iframe a title — the ratio box does not and cannot supply one for them.
Props
Name
Type
Default
Description
ratio
enum: 1:1 | 4:3 | 3:2 | 16:9 | 21:9
16:9
The width:height ratio to enforce on the box.
Examples
16:9 widescreen
Widescreen 16:9 media frame that keeps the video slot stable before content loads.
16:9Video frameStable before the iframe loads
YAML
type: aspect-ratio
props:
ratio: 16:9
slots:
default:
- type: well
props:
padding: spacious
class: layout-demo-media
slots:
default:
- type: stack
props:
gap: xs
direction: column
align: center
children:
- type: badge
props:
variant: muted
slots:
default: 16:9
- type: text
props:
kind: heading
value: Video frame
- type: text
props:
kind: muted
value: Stable before the iframe loads
1:1 square
Square thumbnail or avatar frame constrained by the showcase stage so the shape is obvious.
A flex box that centres its content both horizontally and vertically. The minimum height is an enum (none, small, medium, large, or full viewport) so the common "centre this in the available space" intent is expressed declaratively rather than with a one-off 100vh. Use it for empty states, loading placeholders, and single-focus hero regions.
Readiness
complete
Preview
live
Props
2
Examples
3
Code
implementation mapped
When to use
Centring an empty-state illustration and message
Centring a loading spinner in the available space
A single call-to-action centred in a viewport-tall region
Centring a card in a modal or full-page shell
When not to use
Multiple peer items in a row/column — use Stack
A responsive tile grid — use Grid or Columns
Only horizontal centring of block content — a max-width Container
Centring text within a line — use text-align via the text component
Accessibility
Role: presentation
No keyboard shortcuts
Screen reader: Layout-only; Center adds no role or semantics. The centred child is responsible for its own heading, label, and focus behaviour.
Notes: DOM order matches visual order — Center does not reorder content, so screen-reader sequence stays aligned with the visual presentation.
Props
Name
Type
Default
Description
min_height
enum: none | sm | md | lg | screen
none
Minimum block size of the centring region.
inline
boolean
false
When true, render as inline-flex so the box hugs its child instead of filling the available width.
Examples
Empty state
Centred empty-state message in a panel-sized region.
No resultsTry a different search term.
YAML
type: center
props:
min_height: md
slots:
default:
- type: stack
props:
gap: sm
direction: column
align: center
children:
- type: text
props:
kind: heading
value: No results
- type: text
props:
kind: muted
value: Try a different search term.
Centred spinner
Centred loading spinner.
Loading workspace
YAML
type: center
props:
min_height: sm
slots:
default:
- type: spinner
props:
size: medium
layout: block
slots:
label:
- type: text
props:
kind: muted
value: Loading workspace
Lay out peer content blocks in two, three, or four equal-width columns that collapse to a single column below the small breakpoint so reading order stays obvious on phones. The column count and gap are component props, not one-off utility strings embedded in product screens. Use it for marketing sections, settings groups, and side-by-side prose.
Readiness
complete
Preview
live
Props
2
Examples
3
Code
implementation mapped
When to use
Two or three blocks of prose or settings side by side on desktop
A feature grid that should stack to one column on mobile
Splitting a form into balanced columns at wide widths
Equal-weight peer cards where source order is the reading order
When not to use
A dense N-up tile dashboard with breakpoint-specific counts — use Grid
A linear ordered flow — use Stack so order is unambiguous
A fixed nav rail plus main content — use Sidebar
User-resizable panes — use Splitter
Accessibility
Role: presentation
No keyboard shortcuts
Screen reader: Layout-only; Columns preserves child DOM order. Visual columns must not imply a different reading order — the source order is the order assistive tech announces.
Notes: Children remain responsible for their own headings, roles, and focus states. The single-column collapse keeps narrow-viewport reading order identical to the source order.
Props
Name
Type
Default
Description
count
enum: two | three | four
two
Column count at the wide breakpoint; collapses to 1 when narrow.
gap
enum: sm | md | lg
md
Gap between columns, from the shared token scale.
Examples
Three columns
Three equal feature blocks that collapse to one on mobile.
01FastA peer block with equal desktop weight.
02ComposableColumns preserve source order.
03ObservableThe gap is token-driven.
YAML
type: columns
props:
count: three
gap: md
children:
- type: well
props:
padding: cozy
class: layout-demo-card
slots:
default:
- type: stack
props:
gap: xs
direction: column
children:
- type: badge
props:
variant: primary
slots:
default: '01'
- type: text
props:
kind: heading
value: Fast
- type: text
props:
kind: muted
value: A peer block with equal desktop weight.
- type: well
props:
padding: cozy
class: layout-demo-card
slots:
default:
- type: stack
props:
gap: xs
direction: column
children:
- type: badge
props:
variant: muted
slots:
default: '02'
- type: text
props:
kind: heading
value: Composable
- type: text
props:
kind: muted
value: Columns preserve source order.
- type: well
props:
padding: cozy
class: layout-demo-card
slots:
default:
- type: stack
props:
gap: xs
direction: column
children:
- type: badge
props:
variant: success
slots:
default: '03'
- type: text
props:
kind: heading
value: Observable
- type: text
props:
kind: muted
value: The gap is token-driven.
Two columns
Two-column settings split.
ProfileName, avatar, and contact defaults.
SecuritySessions, MFA, and tokens.
YAML
type: columns
props:
count: two
gap: lg
children:
- type: well
props:
padding: cozy
class: layout-demo-card
slots:
default:
- type: stack
props:
gap: xs
direction: column
children:
- type: text
props:
kind: heading
value: Profile
- type: text
props:
kind: muted
value: Name, avatar, and contact defaults.
- type: well
props:
padding: cozy
class: layout-demo-card
slots:
default:
- type: stack
props:
gap: xs
direction: column
children:
- type: text
props:
kind: heading
value: Security
- type: text
props:
kind: muted
value: Sessions, MFA, and tokens.
Container constrains page content to the platform reading width while preserving the standard page gutter. It is the outer wrapper for normal document-like surfaces where full-bleed chrome would make the content harder to scan.
Readiness
complete
Preview
live
Props
1
Examples
1
Code
implementation mapped
When to use
Pages or panels whose primary content should align to the platform column
Documentation, settings, onboarding, and other reading-first surfaces
A stable outer wrapper before composing Grid, Section, or Stack
When not to use
Full-bleed application chrome such as workspace shells or browser panels
Small repeated cards or list rows; use Card, Section, or Stack instead
Dialogs and overlays, which own their own width and inset rules
Accessibility
Role: presentation
No keyboard shortcuts
Screen reader: Adds no landmark by itself; pair with semantic page regions inside.
Notes: Do not use Container as the only semantic wrapper around a page.
Props
Name
Type
Default
Description
class
string
—
Optional extra class for rare page-level variants.
Examples
Settings page column
A settings page column with a heading and primary action.
Workspace settingsReview access, defaults, and notification preferences.
A thin separator line between content groups. The orientation is an enum (horizontal full-width rule, or a vertical hairline between inline siblings) and the surrounding space is drawn from the shared gap token scale, so a divider can never introduce a magic pixel margin or a one-off border colour. Purely decorative dividers are hidden from assistive tech; set decorative=false when the break is semantically meaningful (e.g. between unrelated record groups).
Readiness
complete
Preview
live
Props
3
Examples
3
Code
implementation mapped
When to use
Separating sections inside a panel or settings group
A vertical hairline between inline toolbar actions
Visually grouping unrelated blocks without a heading
Replacing a raw <hr> so the colour tracks the theme
When not to use
Spacing between flex siblings — use Stack gap or Spacer
A titled, collapsible region — use Section
Card or surface edges — those own their own border
Decorative flourish — a divider is structural, not ornamental
Accessibility
Role: separator
No keyboard shortcuts
Screen reader: A decorative divider (the default) sets role=presentation and aria-hidden so it adds no screen-reader noise. A meaningful divider (decorative=false) is announced as a separator with aria-orientation matching its axis.
Notes: Do not rely on a divider alone to convey grouping for non-visual users — pair semantically distinct groups with headings or labels.
Props
Name
Type
Default
Description
orientation
enum: horizontal | vertical
horizontal
Axis the rule runs along.
spacing
enum: none | sm | md | lg
md
Margin reserved on the cross axis of the rule.
decorative
boolean
true
When true the divider is purely visual and removed from the a11y tree. When false it is announced as a thematic separator.
Examples
Horizontal rule
Default horizontal rule between two text blocks.
AccountManage your profile and security.
YAML
type: well
props:
padding: cozy
class: layout-demo-measure
slots:
default:
- type: stack
props:
gap: none
direction: column
children:
- type: text
props:
kind: heading
value: Account
- type: divider
- type: text
props:
kind: muted
value: Manage your profile and security.
Grid lays out peer items in a responsive column system. It keeps column counts and gaps declared as component props instead of embedding one-off utility strings in product screens.
Readiness
complete
Preview
live
Props
6
Examples
1
Code
implementation mapped
When to use
A set of peer cards, metric rows, settings groups, or navigation tiles
Layouts that need one column on small screens and more columns on wider screens
Dashboard summaries where each child should keep equal visual weight
When not to use
Linear forms or ordered steps; use Stack so reading order remains obvious
Table-like data with headers and cell alignment requirements
Freeform canvas or graph layouts that need custom positioning
Accessibility
Role: presentation
No keyboard shortcuts
Screen reader: Preserves child order in the DOM; visual columns must not imply a different reading order.
Notes: Children remain responsible for their own headings, roles, and focus states.
Props
Name
Type
Default
Description
cols
integer
1
Base column count.
cols_sm
integer
—
Column count at the small breakpoint.
cols_md
integer
—
Column count at the medium breakpoint.
cols_lg
integer
—
Column count at the large breakpoint.
gap
string
1rem
CSS gap value between grid items.
class
string
—
Optional extra class for constrained migration cases.
Examples
Three-column summary
Three equal operational summaries at desktop width.
PageHeader provides the canonical top row for a page or major surface: one visible title, optional actions, and stable spacing. It prevents each view from inventing its own title/action alignment.
Readiness
complete
Preview
live
Props
2
Examples
1
Code
implementation mapped
When to use
Top of a page, library surface, settings view, or major panel body
A title row with one or more right-aligned actions
Screens where the heading should be the first scannable anchor
When not to use
Small card titles or subsection headings; use Section
Modal headers; use Dialog or ModalShell chrome
Navigation breadcrumbs; use Breadcrumb before or alongside the header
Accessibility
Role: banner
No keyboard shortcuts
Screen reader: Renders the page title as the primary heading for the surface.
Notes: Use only once per page-like surface so heading hierarchy stays clear.
Props
Name
Type
Default
Description
title*
string
—
Visible page title.
heading_level
integer
1
Semantic heading level for the title. Keep the default for real pages; use a lower level only when PageHeader is embedded as a specimen inside another document.
Examples
Header with action
A component category header with a primary action.
Section groups related content under a stable heading rhythm. It is the normal boundary inside a page when content needs a label, optional helper text, and a consistent content inset.
Readiness
complete
Preview
live
Props
5
Examples
1
Code
implementation mapped
When to use
Settings groups, documentation blocks, or dashboard subsections
A titled region inside a page-level Container
Advanced areas that can collapse without leaving the page
When not to use
Clickable repeated items; use Card or ItemButton
Page titles; use PageHeader
Expandable FAQ rows; use Disclosure or Accordion
Accessibility
Role: region
Enter — Toggles when the section is collapsible and the header has focus
Space — Toggles when the section is collapsible and the header has focus
Screen reader: Heading text identifies the region; collapsible sections expose expanded state.
Notes: Use concise titles so the region list remains useful.
Props
Name
Type
Default
Description
title
string
—
Optional section heading.
subtitle
string
—
Secondary text under the heading.
collapsible
boolean
false
Whether the header toggles the content.
collapsed
boolean
false
Initial collapsed state when collapsible is true.
class
string
—
Optional extra class for migration-only variants.
Examples
Settings section
A settings section with explanatory copy and a save action.
Notifications
Choose which platform events create alerts.
Operational alerts stay enabled for all admins.
YAML
type: section
props:
title: Notifications
subtitle: Choose which platform events create alerts.
children:
- type: text
props:
kind: muted
value: Operational alerts stay enabled for all admins.
- type: button
props:
variant: secondary
size: small
slots:
default: Edit rules
A two-column shell: a fixed-width rail (navigation, filters, table of contents) beside a flexible main pane that owns its own scroll. The rail width is a token-driven enum and the rail renders as a complementary landmark so keyboard and screen-reader users can move between or skip it. Below the small breakpoint it collapses to a single column, rail first, so nothing is lost on a phone.
Readiness
complete
Preview
live
Props
3
Examples
3
Code
implementation mapped
When to use
A settings screen with a left nav rail and a content pane
Documentation with a table-of-contents rail
A list/detail layout where the list is a persistent rail
A filters rail beside a results pane
When not to use
Equal-weight content columns — use Columns
A user-resizable split — use Splitter
A free N-up tile grid — use Grid
Top navigation rather than a side rail — use a header layout
Accessibility
Role: complementary
No keyboard shortcuts
Screen reader: The rail renders as <aside role="complementary"> with an aria-label, so it is exposed as a distinct landmark that can be navigated to or skipped. The main pane is a plain region following the rail in DOM order.
Notes: Provide a meaningful aria_label describing the rail's purpose (e.g. "Settings navigation"). The single-column collapse keeps the rail before the main content in source order.
Props
Name
Type
Default
Description
side
enum: start | end
start
Which edge the nav rail sits on.
width
enum: sm | md | lg
md
Fixed width of the nav rail.
aria_label
string
Sidebar
Accessible label for the complementary rail landmark.
Examples
Settings layout
Settings screen: nav rail beside a content pane.
ProfileUpdate your name, avatar, and contact defaults.
A zero-flex box that reserves a token-sized amount of space on one axis. Reach for it only when Stack's gap cannot express the spacing — for example a single push between two blocks that are not Stack siblings, or reserving height inside a fixed container. The size is an enum from the shared gap scale, never a raw pixel value, so spacing rhythm stays consistent as the scale evolves.
Readiness
complete
Preview
live
Props
2
Examples
3
Code
implementation mapped
When to use
A one-off push between blocks that are not Stack siblings
Reserving a fixed gap inside a non-flex container
Separating two unrelated regions where a Divider would be too loud
Vertical breathing room before a footer in a fixed-height column
When not to use
Spacing between Stack/flex siblings — use the parent's gap
A visible separator line — use Divider
Pushing items apart in a flex row — use flex-grow on a real element
Page-level layout regions — use Grid or Sidebar
Accessibility
Role: presentation
No keyboard shortcuts
Screen reader: The spacer sets role=presentation and aria-hidden so it is entirely invisible to assistive technology — it carries no content.
Notes: Spacing must never be the only thing conveying a grouping boundary for non-visual users; use headings or labels for meaningful breaks.
Props
Name
Type
Default
Description
size
enum: xs | sm | md | lg | xl
md
Gap size, drawn from the shared token scale.
axis
enum: vertical | horizontal
vertical
Axis the gap is reserved on.
Examples
Vertical gap
Vertical gap between two unrelated blocks.
BillingNext invoice on the 1st.
YAML
type: well
props:
padding: cozy
class: layout-demo-measure
slots:
default:
- type: stack
props:
gap: none
direction: column
children:
- type: text
props:
kind: heading
value: Billing
- type: spacer
props:
size: lg
- type: text
props:
kind: muted
value: Next invoice on the 1st.
Two panes separated by a draggable handle. The user drags (pointer) or uses the keyboard (arrows to nudge, Home/End to collapse) to change the split. The handle is a true ARIA separator carrying live value semantics, the split fraction is clamped to a sane range, and the drag/keyboard state uses Arc reactive primitives so the component is safe inside disposing <Show>/<For> scopes.
Readiness
complete
Preview
live
Props
3
Examples
3
Code
implementation mapped
When to use
A side-by-side editor and preview that the user can resize
A list/detail layout where the user controls the split
Two panels that should share space on a ratio the user owns
A diff view with adjustable before/after panes
When not to use
A fixed-width nav rail plus content — use Sidebar
Equal-weight, non-resizable columns — use Columns
A free tile grid — use Grid
Simple stacked content — use Stack
Accessibility
Role: separator
ArrowLeft — Shrink leading pane (horizontal split)
ArrowRight — Grow leading pane (horizontal split)
ArrowUp — Shrink leading pane (vertical split)
ArrowDown — Grow leading pane (vertical split)
Home — Collapse the leading pane toward minimum
End — Grow the leading pane toward maximum
Screen reader: The handle is role="separator" with tabindex 0, an aria-label, aria-orientation matching the separator axis (perpendicular to the split direction), and aria-valuemin / aria-valuemax / aria-valuenow reporting the current split percentage.
Notes: aria-orientation is the orientation of the separator itself, which is perpendicular to the split: a side-by-side (horizontal) split has a vertical separator. The handle is fully keyboard operable so a pointer is never required.
Props
Name
Type
Default
Description
orientation
enum: horizontal | vertical
horizontal
Split axis.
initial
number
50
Initial size of the leading pane, in percent (clamped 8–92).
aria_label
string
Resize panes
Accessible label for the resize handle.
Examples
Horizontal split
Side-by-side editor and preview the user can resize.
EditorPrompt and configuration pane
PreviewLive output stays beside the editor
YAML
type: splitter
props:
orientation: horizontal
initial: 50
aria_label: Resize editor and preview
slots:
leading:
- type: well
props:
padding: cozy
class: layout-demo-pane
slots:
default:
- type: stack
props:
gap: sm
direction: column
children:
- type: badge
props:
variant: primary
slots:
default: Editor
- type: text
props:
kind: muted
value: Prompt and configuration pane
trailing:
- type: well
props:
padding: cozy
class: layout-demo-pane
slots:
default:
- type: stack
props:
gap: sm
direction: column
children:
- type: badge
props:
variant: muted
slots:
default: Preview
- type: text
props:
kind: muted
value: Live output stays beside the editor
Vertical or horizontal flex container with gap, direction, and alignment drawn from token-driven enums. The single canonical way to express spacing rhythm in a panel.
Readiness
complete
Preview
live
Props
3
Examples
3
Code
implementation mapped
When to use
Vertical column with consistent spacing — `direction: column`
Horizontal row with consistent spacing — `direction: row` (no separate Inline component)
Replacing inline-style margins/padding between siblings
Form field stacking (use with `field` children)
When not to use
2D grid layouts — use Grid
Centering a single child — use Center primitive (when it lands)
Inline text wrapping — Stack is block-flex, not inline
Splittable resizable panes — use Splitter (when it lands)
Accessibility
Role: presentation
No keyboard shortcuts
Screen reader: No semantic role; layout-only. DOM order matches visual order — do not use flex-order to reorder, as it diverges screen-reader from visual sequence.
Notes: For grouped form controls, wrap with `<fieldset>` (use Fieldset primitive) for proper form-association semantics.
Props
Name
Type
Default
Description
gap
enum: none | xs | sm | md | lg | xl
md
Gap between children. Token-driven; the px values live in CSS and change globally if the spacing scale changes.
direction
enum: column | row
column
align
enum: start | center | end | stretch
stretch
Cross-axis alignment of children.
Examples
Login form stack
Login form fields and submit button (replaces inline-style spacing in PasswordLoginForm).