# Composure – Core Invariants

## The rule

Parents compose children. Children describe themselves; parents decide.

## Vocabulary

**Node** — a retained element in the tree. Has a tag, children, and a frame.

**Key** — optional stable identity for a node across updates.

**Frame** — `{ x, y, width, height }` — the room a parent assigns to a child. Always set by the parent, never by the child.

**Constraints** — the measurement budget a parent gives a child. In v1: `{ maxWidth, maxHeight }`.

**Layout function** — a parent strategy that measures direct children, assigns each child's `.frame`, and returns the parent's measured size.

**Layout mode** — a named built-in layout strategy: `vstack`, `hstack`, `zstack`. A parent may also supply a custom layout function.

**Size** — `size(w, h)` — intrinsic size hints for the layout engine. Not CSS. Not passed to the DOM. Consumed only during measurement and placement.

**Style** — `style({...})` — visual CSS properties only (background, color, borderRadius, etc.). Layout-owned properties (position, width, height, margin, display) are silently rejected — those belong to `size()` and the frame. Passed directly to the DOM element.

**Overflow** — visual extent outside the assigned frame. May affect clipping or decoration, but does not change frame ownership.

**Decorate** — `decorate(fn, opts)` — runs after layout with resolved geometry. The callback receives `{ el, svg, frame, children }`. Use `el` for direct DOM access. Use `svg` to draw vector overlays (path, rect, circle, line, group). Decorations read frames; they do not set frames.

**Hint** — `hint({...})` — optional layer/compositing hints forwarded to CSS (will-change, contain, isolation, etc.). They do not affect layout or frame ownership, and they do not guarantee browser promotion. Frames are decided by layout; layers are decided by rendering.

**On** — `on(event, handler)` — binds a DOM event handler. The listener is attached once per event type; calling `.on()` again with the same event swaps the handler without touching the DOM listener. Pass `null` to disable. Use `.off(event)` to remove.

**Grow** — `grow(factor)` — hints that this child should take a share of remaining space in a stack. Non-growing children are measured first, then remaining space is distributed proportionally.

**Transition** — `transition({ duration, easing })` — enables CSS transition animation for frame changes. Frames animate when position or size changes. Use `.noTransition()` to disable.

**Dirty** — a node is dirty when it needs re-measurement. Mutations mark nodes dirty automatically. Dirty state propagates up to ancestors. Clean nodes with unchanged constraints skip layout.

**Mount** — connects a root node to a DOM container. Runs layout, renders DOM, and re-layouts on resize.

## Phases

1. **Build** — construct the retained tree with plain JS
2. **Layout** — recursive measure + place (parent measures direct children, assigns frames)
3. **Render** — emit positioned DOM elements

## Rules

1. A child's frame is set by its parent. Never by the child itself.
2. Children measure within constraints and return a size. They do not negotiate.
3. Parents own placement; children own internal rendering.
4. Layout is local. A parent sees only its direct children.
5. No global solving. No cross-parent dependencies.
6. At most one refinement pass, and only the parent may request it.
7. The browser measures text. The runtime places everything.
8. DOM output preserves semantics — real tags, roles, focusable elements.
9. `size()` is for the layout engine. `style()` is for the browser. `hint()` is for the compositor. They never cross.

## Built-in layout modes

| Mode | Behavior |
|------|----------|
| `vstack` | Stack children vertically. Cross-axis alignment via `.align()`. Supports `.grow()` for flexible space distribution. |
| `hstack` | Stack children horizontally. Cross-axis alignment via `.align()`. Supports `.grow()` for flexible space distribution. |
| `zstack` | Overlay children in the same parent space. Default: stretch to fill. Supports start, center, end via `.align()`. |
| custom | Parent supplies a layout function. |

## What the runtime owns

- Tree structure and keyed reconciliation
- Measurement orchestration and caching
- Frame assignment
- Dirty tracking and incremental layout
- DOM emission and patching
- Style/attribute cleanup (stale removal)
- Resize re-layout
- Frame animation (via CSS transitions)

## What the browser owns

- Text shaping and wrapping
- Intrinsic leaf measurement
- Accessibility
- Focus and input
- Event dispatch
- Painting and compositing (layer promotion is a hint, not a guarantee)
