--- title: Building a Component — the one door type: guide audience: human + agent authority: navigational — THE entry point for building a new component; content lives in the linked docs status: current related: acceptance: src/uix/COMPONENT_COMPLETION_CHECKLIST.md (when is it done — machine-audited) soma: src/uix/soma/COMPONENT_GUIDE.md (the deepest phase doc) --- # Building a Component — the one door Read **this file first and only this file**. Building a component crosses the four layers and the theming system; the knowledge lives in eight documents that each own one phase. Nobody should have to discover that chain by archaeology — this doc IS the chain. Each phase names **the one document to read**, what you produce, and the guard that verifies it. Role note (authoring rule 4 — one source per concern): this doc contains **no content**, only sequencing. If a phase doc and this table disagree about order, this doc wins on *order*; the phase doc wins on *content*. --- ## The route | Phase | You produce | Read THIS | Verified by | | --- | --- | --- | --- | | **0 · Decide** | comparison table vs ark/bits/radix (+ react-aria), membership call (soma or eidos-native), compose-first check | [`soma/COMPONENT_GUIDE.md`](../src/uix/soma/COMPONENT_GUIDE.md) §Before You Start (1–4) · membership: [`soma/README.md`](../src/uix/soma/README.md) §2 | reviewer — the table goes in the component README (phase 7) | | **1 · Morfo** | `src/uix/morfo/components/{kebab}.ts` — parts, data/aria, keyboard, events (family/verb/intent/sequence), `texts`, `expression` | [`morfo/README.md`](../src/uix/morfo/README.md) §Authoring a new morfo · vocabulary: [`CANON.md`](./CANON.md) | `validateMorfo` + `npm run morfo:vocabulary` + audit `A-*` | | **2 · Soma** | `{kebab}-provider.svelte.ts` + thin wrappers + `types.ts` + provider test | [`soma/COMPONENT_GUIDE.md`](../src/uix/soma/COMPONENT_GUIDE.md) (patterns + rules A1–A37) | provider test + `npm run check` | | **3 · Sema** | pack `src/uix/sema/components/{kebab}.ts` (or explicit `expression: 'family-default'`) — selectors via `semaSelector` ONLY | [`sema/README.md`](../src/uix/sema/README.md) §packs + §typed builder · pack-vs-default criteria: [`LIBRO_VARIACIONES`](../src/docs/LIBRO_VARIACIONES_Y_EXTENSIONES.md) D.4 | `npm run morfo:vocabulary` (expression coverage) | | **4 · Eidos wrapper** | `eidos/components/{kebab}/` — root + attached parts (option C), visual props | [`eidos/components/README.md`](../src/uix/eidos/components/README.md) (the 7 hard rules) | `component-api-contract` test + audit `E-*` | | **5 · Recipe + theming** | recipe tokens in `lib/recipes/base.ts` + `{kebab}.css` | [`eidos/THEMING_GUIDE.md`](../src/uix/eidos/THEMING_GUIDE.md) pasos 1–6 · **mandatory contract**: [`eidos/RECIPE_CONTRACT.md`](../src/uix/eidos/RECIPE_CONTRACT.md) · scope (if `data-color`): [`eidos/TSC.md`](../src/uix/eidos/TSC.md) | `npm run generate:eidos-css` + `recipe-css-contract` test + audit `R-*` (R-4.x = the contract) | | **6 · Demo** | `web/routes/uix/components/{kebab}/+page.svelte` — v2 9-tab layout | [`DEMO_AUTHORING_GUIDE.md`](../web/routes/uix/lib/DEMO_AUTHORING_GUIDE.md) | audit `D-*` + `npm run smoke` | | **7 · Component README** | Baseline · Comparativa (≥3 refs) · Decisiones · Gaps-with-disposition · Sema events table | template = any recent PASS component's README; sections audited | audit `F-*` | | **8 · Acceptance** | nothing new — the component passes | [`COMPONENT_COMPLETION_CHECKLIST.md`](../src/uix/COMPONENT_COMPLETION_CHECKLIST.md) | `npm run component:audit --only {kebab}` + `npm run morfo:check` + `eidos-lint` | Cross-phase invariants you will hit in every phase: the layer boundaries ([`active_architecture.md`](../src/uix/active_architecture.md) §7 hard rules) and the 2-of-3 rule for extending morfo ([`morfo/README.md`](../src/uix/morfo/README.md)). --- ## Known traps — sections that LOOK authoritative but are superseded The corpus still carries superseded material inline. Until the cleanup pass lands, do **not** follow these: | If you read… | The truth is… | | --- | --- | | `translations:` field in morfo examples (morfo/README, SOMA_ARCHITECTURE §7) | The field is **`texts:`** (idlangrefs). `translations:` does not compile — audit rule A-1.3 flags it. | | THEMING.md §13 (`event:*` TSC scope) + §14's `data-motion-ref` | Superseded — the motion model is [`eidos-motion.md`](../src/uix/eidos/eidos-motion.md) (two moments, signatures in `EidosConfig.motion`). | | GUIA_IMPLEMENTACION §5.3 (`defaultSemantic`) | The implemented shape is additive `allowedFamilies` ([`LIBRO_VARIACIONES`](../src/docs/LIBRO_VARIACIONES_Y_EXTENSIONES.md) D.11). | | GUIA_IMPLEMENTACION §6.2 holds table / §4.1 dialog=shift | Code + [`CANON.md`](./CANON.md) win: holds live in `SEMA_MAP` / `holds.ts`; Dialog's events are `emerge` in its morfo. | | soma/README §3 deps (`@floating-ui`, `clsx`) | Positioning is the in-house engine (`soma/layers/floating` + `$ethereal`); those deps are gone/dev-only. | | A 6-tab demo `type Tab` union in older demos | The canonical layout is the v2 **9-tab** union (DEMO_AUTHORING_GUIDE); v1 is accepted only pending migration. | | "24 archetypes" (active_architecture §6, morfo/README) | `ARCHETYPE_VOCABULARY` in `morfo/types.ts` is the source (26 today — the const wins over any count in prose). | Golden rule when a doc contradicts code: **code + CANON.md win** — and open an issue/fix for the doc (THEMING.md's own footer says the same).