Design System Contracts

Spec reference

Layout

Flexbox and auto-layout are the same declaration here — plus per-variant overrides for the cases where a value legitimately deviates.

The layout blockGeneratedCurated#

One vocabulary, two projections: flexbox on the code side, auto-layout on the canvas. The properties are the intersection both surfaces can honor — that is the point.

display"flex" | "inline-flex"

flex or inline-flex (code); auto-layout either way on the canvas.

direction"row" | "column"

Row or column. Reversed directions exist only as per-variant overrides (see below) — the canvas has no reverse, so they are compiled away.

align"start" | "center" | "end" | "stretch" | "baseline"

Cross-axis alignment.

justify"start" | "center" | "end" | "space-between"

Main-axis distribution.

growboolean

The part takes remaining space — code: flex: 1 1 auto; canvas: fill container.

overlapboolean

Children overlap (AvatarGroup): the gap token is applied as a negative child margin in CSS and as negative item spacing on the canvas.

wrapboolean

v15: children wrap (tag groups, chip rows) — code: flex-wrap: wrap; canvas: native layoutWrap: WRAP.

contracts/avatar-group.contract.json (excerpt · v1.0.0) — shipping contract, loaded at build time · overlap — the negative-spacing projection
{
  "anatomy": {
    "root": {
      "parts": {
        "stack": {
          "layout": {
            "direction": "row",
            "align": "center",
            "overlap": true
          },
          "tokens": {
            "gap": "{space.avatarGroup.overlap}"
          }
        }
      }
    }
  }
}

hugsBelowMaxWidth — measured sizing evidenceCurated#

hugsBelowMaxWidth: boolean on a part answers one question about that part's max-width channel: is this a ceiling the box normally sits under, or the width the box is actually drawn at? A CSS max-width alone cannot tell you, and the two answers lower to opposite things on the canvas — hug-contents versus a fixed width.

The flag is measured, never assumed. The computed capture sets it to true only when the used width stayed strictly below the cap in every enumerated combination, which means the box hugs and the cap is a ceiling. A width equal to the cap means the box is sitting at it and the value may be a genuine design width, so the flag is not set and the fixed-width lowering stands. A contract with no captured evidence omits the field and keeps the design-width lowering — which is why hand-authored contracts are unaffected by its existence.

Refusals: Each of these fails the build by name — the generator refuses, it never papers over (source: core/emit-react.ts validateContract, exercised by the C2 eval family).

  • a part carrying hugsBelowMaxWidth with no max-width channel — the flag qualifies that channel and qualifies nothing else

Layout by propGeneratedCurated#

layoutByProp: { prop, map } applies per-enum-value layout overrides merged over the base layout. Partial coverage is the point — only the values that deviate appear. ChatMessage: sender=user flips direction: row-reverse on the root, right-aligning user messages.

Projections: code emits the override under the root’s enum class (.sender-user .body { … }); the canvas — which has no reverse — resolves it per variant at compile time, rendering the same children in reversed order.

layoutByProp.map values — VariantLayout, rendered from the schema
map values: VariantLayout

Refusals: Each of these fails the build by name — the generator refuses, it never papers over (source: core/emit-react.ts validateContract, exercised by the C2 eval family).

  • the driving prop must be a declared enum; every map key one of its values
  • a component-instance part refuses overrides — the child contract owns its layout
  • grow and overlap stay per-part invariants: not overridable per variant
contracts/chat-message.contract.json (excerpt · v1.1.0) — shipping contract, loaded at build time
{
  "anatomy": {
    "root": {
      "layoutByProp": {
        "prop": "sender",
        "map": {
          "user": {
            "direction": "row-reverse"
          }
        }
      }
    }
  }
}