The layout tree
Every node has a type; containers have children and primitives do not; common layout props apply to any node.
The layout tree
Every node has a type. Container nodes have children; primitives do not — if you can picture the DOM, you can picture a spec.
Examples
A row of icon + heading:
A nested column with spacing, a badge and a primary action:
Anatomy
_id
A stable, human-meaningful identifier for the node. It is not required, but give nodes real names ("menu-header", not "row-4") — _id is how patches address a node across edits, and auto-generated-looking IDs are flagged by the validator's lint pass for exactly that reason.
Common layout props
These apply to any node type.
| Prop | Type | Notes |
|---|---|---|
gap | number | Space between children, in px. |
padding | number | string | 24, "12 16" (v h), or "8 12 8 12" (t r b l). |
flex | number | Flex grow factor. |
width, height | number | string | 120, "100%", "auto". |
align | string | Cross axis: start, center, end, stretch. |
justify | string | Main axis: start, center, end, space-between, … |
scroll | boolean | Direction-aware: horizontal on row, vertical elsewhere. |
background | string | A background token name, a hex value, a CSS gradient string, or a url(...) image fill. |
border | string | all, top, bottom, left, right. |
radius | "sm" | "md" | "lg" | number | Corner radius. |
elevation | 0–5 | A layered, theme-aware shadow ladder. shadow "sm"/"md"/"lg" are aliases for steps 1–3. |
shadow | boolean | string | "sm", "md", "lg" presets — or any CSS box-shadow string. |
hover, press, focus | object | A CSS bag applied in that state. Semantic colour words and var(--token) resolve. |
style | object | Raw CSS past the passthrough allowlist, applied last; var(--token) resolves. |
animate | string | Appear animation preset, or a keyframe name the active style defines. Plays on mount; respects prefers-reduced-motion. |
showWhen / hideWhen | string | Conditional visibility — see State & expressions. |
slot | string | Marks a container as an inline slot target. |
instructions | string[] | Behavior notes for humans and code generators. Not rendered. |
Motion companions (animateDuration, animateDelay, animateEasing, animateIterations, animateOn, animateStagger, parallax, scrub, mask, aspectRatio, safeArea) are documented in the format reference §4 and on the Motion page.
CSS passthrough
Beyond the semantic props, any node accepts a set of raw CSS properties (camelCase) that forward directly to the rendered element's inline style — on plain nodes and component instances alike. Semantic props win where they overlap; passthrough fills in the rest.
Positioning and box: position (including sticky), top/right/bottom/left, zIndex, overflow/overflowX/overflowY, minWidth/minHeight/maxWidth/maxHeight, order, per-side margin*/padding*, boxShadow, borderRadius, per-side border*, backgroundColor.
Motion: transition, animation, animationDelay, animationDuration, transform, transformOrigin, willChange.
Compositing: opacity, mixBlendMode, backgroundImage, backgroundSize, backgroundPosition, backgroundRepeat, backgroundClip + WebkitBackgroundClip, WebkitTextFillColor, textShadow, clipPath, maskImage + WebkitMaskImage, backdropFilter, filter.
Grid: gridTemplateColumns, gridTemplateRows, gridColumn, gridRow — an authored template wins over the columns: N default.
Typography and text flow: letterSpacing, lineHeight, textDecoration, textTransform, fontStyle, whiteSpace, textOverflow, wordBreak, wordWrap.
Interaction and scroll: cursor, scrollSnapType, scrollSnapAlign.
The second widening added 3D and the standalone transforms (perspective, transformStyle, backfaceVisibility, rotate/scale/translate as strings), font axes (fontVariationSettings, fontFeatureSettings, textWrap, WebkitLineClamp, hyphens, textIndent), outline*, pointerEvents, userSelect, visibility, touchAction, inset, margin, the flex and border longhands, per-corner radii, the animation longhands, the scroll properties and viewTransitionName.
A property outside the allowlist is stored and not rendered, and validation says so. style: { … } is the escape hatch for exactly that case — raw CSS on any node, sanitized, applied last.
Stability
Layout props and the CSS passthrough allowlist are part of the format contract: adding a prop is additive; removing one or narrowing its accepted values is breaking. The allowlist itself is checked against KNOWN_CSS_PROPERTY_NAMES in the validator.
Flows
Flows record navigation edges between screens — documentation of intent and the input to reachability analysis, not the navigation mechanism; a timed link carries its delay.
Requirements
A document carries its requirements beside the screens that answer them — what the product must do, the criteria that say it does, and links validate() checks.