Architecture
Location:packages/core/src/layout/layout.ts
Intrinsic Sizing Protocol
Every widget implements two measurement functions:Min-Content Size
The smallest size at which the widget can render without overflow:- Text: Width of longest word (no wrapping within words)
- Button: Width of label + padding
- Input: Minimum viable input width (typically 10 cells)
- Column: Max of children’s min-content widths
- Row: Sum of children’s min-content widths + gaps
Max-Content Size
The ideal size for the widget without external constraints:- Text: Full unwrapped text width
- Button: Full label width + padding
- Input: Desired width (from props) or max-content of placeholder
- Column: Max of children’s max-content widths
- Row: Sum of children’s max-content widths + gaps
packages/core/src/layout/engine/intrinsic.ts
Flex Layout Algorithm
Implements a flexbox-style layout forrow and column widgets.
Stack Layout Properties
Flex Algorithm Steps
- Measure children — compute min-content and max-content for each child
- Resolve flex-basis — determine initial main-axis size
- Distribute space:
- If container larger than sum: grow children with
flex > 0 - If container smaller than sum: shrink children with
flexShrink > 0
- If container larger than sum: grow children with
- Align cross-axis — apply
alignSelfper child - Handle wrapping — split into lines if
wrap: true - Justify main-axis — distribute remaining space per
justify
packages/core/src/layout/engine/flex.ts
Growth Distribution
When space remains after laying out all children:Shrink Distribution
When children exceed available space:packages/core/src/layout/engine/distributeInteger.ts
Grid Layout Algorithm
Implements CSS Grid-style layout with auto-placement and explicit positioning.Grid Properties
Grid Algorithm Steps
- Build occupancy map — track which cells are occupied by explicit placements
- Place explicit children — children with
gridColumn/gridRowset - Auto-place remaining — find next available cell for each child
- Measure tracks:
- Fixed tracks: use explicit size
- Auto tracks: use max-content of cells in track
- Distribute space — grow/shrink tracks to fit container
- Position children — assign final coordinates based on track positions
packages/core/src/layout/kinds/grid.ts
Auto-Placement Algorithm
For children without explicitgridColumn/gridRow:
Box Layout
Box widgets create a synthetic inner column that:- Honors
box.gapbetween children - Excludes absolute-positioned children from flow
- Applies padding and border
packages/core/src/layout/kinds/box.ts
Absolute Positioning
Children withposition: "absolute" are removed from normal flow:
- Positioned relative to nearest positioned ancestor
- Does not affect siblings’ layout
- Computed after all flow layout completes
packages/core/src/layout/positioning.ts
Text Wrapping
Text widgets support wrapping with grapheme-aware line breaking:- Split text into lines on
\ncharacters - For each line, measure width in terminal cells
- If width exceeds constraint:
- Find last grapheme cluster boundary before width
- Split at boundary (never within a grapheme cluster)
- Continue with remaining text on next line
packages/core/src/layout/textMeasure.ts
Constraint Resolution
The layout engine resolves constraints in multiple passes:Pass 1: Measure
Bottom-up measurement:- Leaf nodes measure their intrinsic size
- Container nodes measure based on children
- Cache measurements to avoid redundant work
Pass 2: Constrain
Top-down constraint propagation:- Root receives viewport size as constraint
- Containers distribute constraints to children
- Flex/grid algorithms resolve sizing
Pass 3: Position
Top-down position assignment:- Root positioned at
(0, 0) - Containers position children based on layout algorithm
- Absolute-positioned children positioned relative to ancestor
packages/core/src/layout/engine/layoutEngine.ts
Responsive Layouts
Layout scalars support responsive breakpoints:- Breakpoints:
xs(0),sm(40),md(80),lg(120) - Linear interpolation between breakpoints
- Clamped at edges
packages/core/src/layout/responsive.ts
Overlay Constraints
Overlays (modals, dropdowns, tooltips) have special sizing constraints:- Compute available space in each direction from anchor
- Choose placement with most space
- Constrain size to fit within viewport
packages/core/src/layout/dropdownGeometry.ts
Performance Optimizations
Measurement Caching
Intrinsic measurements are cached per node:Dirty Tracking
Only recompute layout for nodes that changed:packages/core/src/layout/engine/dirtySet.ts
Integer Distribution
Weighted integer distribution for deterministic flex/grid sizing:- Sum of results equals
totalexactly - Deterministic (same inputs → same outputs)
- Proportional to weights
packages/core/src/layout/engine/distributeInteger.ts
Layout Tree Output
- Origin
(0, 0)is top-left of viewport - All measurements in terminal cells (character positions)
- Fractional coordinates not supported (terminal cells are discrete)
Related Documentation
- Render Pipeline — How layout fits in the pipeline
- Protocol Overview — Binary format for rendering
- Benchmarks — Layout performance measurements