Motivation
Reusing components as fixed artefacts is showing its age now that agents write most of the code. A design system is better thought of as a shared language: the identity of each component (intent, anatomy, layout, styles), a contract for the code render, and behaviour guidelines in words. Components then become renders of that identity — the viewer canvas, HTML/CSS, React, and Figma — instead of the thing itself.
The .uidx file is the natural home for that identity, on one condition: declare, never compute. No TypeScript blocks, no when conditions. Implementation is a renderer's job.
Decisions (ADRs 0012–0017)
- 0012 Design-system model. Identity + contract + behaviour guidelines; components are renders.
- 0013 Component contract. A
## Contract region: props, events, slots, form, accessibility, composes. implements binds a component to a headless element, part binds a node to one of its parts. <Prop sample> gives a demonstration value. <State> only for states the element produces itself; <Part> descriptions are optional. The identity never spells a library: uidx.json may carry a library profile and per-component bindings.
- 0014 Behaviour guidelines.
## Behavior as short - id: sentence bullets beside the JSX.
- 0015 Models and examples. View models declared once and shared across pages, named by a prop's type; every field explained; samples for demonstration only; nothing derived.
## Examples are sample scenes.
- 0016 Variants as renders. A
<Styles> table keyed by visual enum props and states derives the variant set. Enum props are axes, visual booleans are states, hover/focus/active need no declaration. Derived variants are addressable: a state is designed on the canvas and the row is written.
- 0017 Collections and code targets.
repeat="{items}" on any layer of a component (with as; nested repeats over {item.children} make a tree; a repeat on a <Slot> is the consumer-fillable one, a render prop in React); slots and render props in React; compositions render the instance they hold; shadow parts through ::part(); codegen config shared by the CLI and the viewer.
Delivered (all in #36)
- format: the four regions, the
<Styles> table, the repeat/as attributes, spec types, diagnostics UIDX140–152, the style and contract patch ops with inverses; uidx fmt preserves the regions; the contract-only helpers (axes, state kinds) live here.
- schema: derived variant sets, sample bindings, repeat expansion,
derivedTarget, contractJson, auditDesignSystem with a shared model index; pass-through instance props resolve in the consumer's scope; slots hug; whole-attribute paint aliases compose strokes.
- codegen (new
@uidx/codegen): HTML/CSS and React 19 over headless custom elements, contract JSON, conformance against custom-elements.json, shadow parts, library profiles (attribute / data-attribute / class, element / css-part / data-part) and bindings.
- server:
uidx.json gains headless (path or { manifest, profile, bindings }) and codegen (out, targets); routes serve the library, discover libraries from dependencies' customElements, write the choice, and generate code. The symbol lint reads contract props.
- viewer: a Contract tab beside Design — implements picker, parts bound from either end, a Repeat block on any layer (list, item name), library picker, the contract itself editable with "Fill from library", a Generate button; derived variants selectable and editable on the canvas with the row written; a Repeat tool in the toolbar.
- cli:
uidx check runs the audit over the whole document; uidx contract; uidx codegen reads headless and codegen from uidx.json.
- examples/design-system: Checkbox, Field, CheckboxField, Button, ContactOption, ContactList over
@hwc/components, generated output committed with a drift test, a Vite demo page; uidx check passes on the whole document.
Later (own issues when reached)
- Theming beyond modes; Figma export of derived sets and repeats;
SPEC.md generation.
Implemented in #36.
Motivation
Reusing components as fixed artefacts is showing its age now that agents write most of the code. A design system is better thought of as a shared language: the identity of each component (intent, anatomy, layout, styles), a contract for the code render, and behaviour guidelines in words. Components then become renders of that identity — the viewer canvas, HTML/CSS, React, and Figma — instead of the thing itself.
The
.uidxfile is the natural home for that identity, on one condition: declare, never compute. No TypeScript blocks, nowhenconditions. Implementation is a renderer's job.Decisions (ADRs 0012–0017)
## Contractregion: props, events, slots, form, accessibility, composes.implementsbinds a component to a headless element,partbinds a node to one of its parts.<Prop sample>gives a demonstration value.<State>only for states the element produces itself;<Part>descriptions are optional. The identity never spells a library:uidx.jsonmay carry a libraryprofileand per-componentbindings.## Behavioras short- id: sentencebullets beside the JSX.## Examplesare sample scenes.<Styles>table keyed by visual enum props and states derives the variant set. Enum props are axes, visual booleans are states,hover/focus/activeneed no declaration. Derived variants are addressable: a state is designed on the canvas and the row is written.repeat="{items}"on any layer of a component (withas; nested repeats over{item.children}make a tree; a repeat on a<Slot>is the consumer-fillable one, a render prop in React); slots and render props in React; compositions render the instance they hold; shadow parts through::part();codegenconfig shared by the CLI and the viewer.Delivered (all in #36)
<Styles>table, therepeat/asattributes, spec types, diagnostics UIDX140–152, thestyleandcontractpatch ops with inverses;uidx fmtpreserves the regions; the contract-only helpers (axes, state kinds) live here.derivedTarget,contractJson,auditDesignSystemwith a shared model index; pass-through instance props resolve in the consumer's scope; slots hug; whole-attribute paint aliases compose strokes.@uidx/codegen): HTML/CSS and React 19 over headless custom elements, contract JSON, conformance againstcustom-elements.json, shadow parts, library profiles (attribute/data-attribute/class,element/css-part/data-part) and bindings.uidx.jsongainsheadless(path or{ manifest, profile, bindings }) andcodegen(out,targets); routes serve the library, discover libraries from dependencies'customElements, write the choice, and generate code. The symbol lint reads contract props.uidx checkruns the audit over the whole document;uidx contract;uidx codegenreadsheadlessandcodegenfromuidx.json.@hwc/components, generated output committed with a drift test, a Vite demo page;uidx checkpasses on the whole document.Later (own issues when reached)
SPEC.mdgeneration.Implemented in #36.