docs(corpus): add docs/comparison.md — honest framework-level positioning

Where UIX sits relative to the two families (headless behavior: Radix/Ark/bits/
React Aria; styled systems: Mantine/Chakra/Radix Themes/shadcn), grounded in
UIX's own documented design choices rather than claims about competitors'
internals:

- morfo as a single declarative contract (compile-time drift),
- a perception layer (sema) neither family has,
- two-moment motion, theme-as-retint, validated token scope, graceful
  degradation,
- and the honest trade-offs (more to learn, smaller ecosystem, sema only pays
  off if used).

The one competitor-specific claim (Chakra collapses presence onto one axis) is
sourced in eidos-motion.md. Per-component prop-parity comparisons stay in each
component README, by doctrine. Wired into docs/README.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
active-uix
dev 4 months ago
parent e737f0f78d
commit 9272c54278

@ -111,6 +111,7 @@ and the server-authoritative engines in `src/svrs/`.
| --- | --- |
| Run it and make a first change | [`docs/getting-started.md`](./getting-started.md) |
| Understand the framework | `src/uix/README.md` → `active_architecture.md` |
| Know why UIX, not Radix / Mantine | [`docs/comparison.md`](./comparison.md) |
| Know what a family / intent / verb means | `docs/CANON.md` |
| Build a new component | `soma/COMPONENT_GUIDE.md` |
| Know if a component is finished | `src/uix/COMPONENT_COMPLETION_CHECKLIST.md` (`npm run component:audit`) |

@ -0,0 +1,95 @@
---
title: How UIX Compares
type: notes
audience: human + agent
status: current
---
# How UIX Compares
An honest read of where UIX sits relative to the field. This is **framework-level
positioning** grounded in UIX's own documented design choices — not a feature
matrix of competitors' internals. The **per-component** prop-parity comparisons
(against ark-ui, bits-ui, radix-ui, react-aria) live in each component's
`README.md`, by project doctrine; this doc is the layer above them.
## Two families exist
Component libraries cluster into two families, and they force a trade:
- **Headless behavior** (Radix Primitives, Ark UI, bits-ui, React Aria) — solve
behavior + accessibility, leave visuals to you. Excellent separation, but they
stop at behavior: there is no model of *what an interaction means* or how it
should *feel*.
- **Styled systems** (Mantine, Chakra, Radix Themes, shadcn) — ship opinionated
visuals and theming, but couple behavior and appearance and let a theme
redefine almost anything.
UIX keeps the headless family's strict separation and adds the two things neither
family has: a **declarative contract** above behavior, and a **perception layer**
below visuals.
## What UIX adds
### 1. A single declarative contract (`morfo`)
A component's public DOM surface — parts, `data-*`, ARIA, keyboard, events — is
declared once in a typed object and consumed by every layer. Rename a part and
the consuming layers break at **compile time**. In the headless libraries that
structural information is spread across the provider, the ARIA derivations, the
CSS and the docs, and drifts silently. → [`morfo/README`](../src/uix/morfo/README.md)
### 2. A perception layer (`sema`)
UIX models the **meaning and feel** of an interaction: 8 perceptual families,
intents (the evaluative load), verbs, and a cascade that projects the signal as
sound, haptic and a `data-event-*` stamp. No mainstream component library has a
perceptual layer — they animate, but they do not have a vocabulary for *what
occurred*. The vocabulary is grounded in the book *Diseñando lo que ocurre*. →
[`CANON.md`](./CANON.md), [`sema/README`](../src/uix/sema/README.md)
### 3. Two-moment motion
UIX animates **two** moments and integrates them with the perceptual signature:
`--event` (the flourish during a signal's hold) and `--state` (the transition to
a persistent condition). The other systems collapse presence animation onto a
single axis (e.g. Chakra: only `data-state` + `Presence`). → [`eidos-motion.md`](../src/uix/eidos/eidos-motion.md)
### 4. Theme = retint the perceptually-fixed
Variants (`solid`/`outline`/…) and the 9 color roles are **canon of the system**,
not of the theme. A theme changes *which hex* is `affirm`; it cannot invent a
variant or redefine what `outline` means. This is the opposite of styled systems
where a theme can redefine almost anything — UIX trades that freedom for
portability and a stable perceptual meaning across themes. → [`THEMING.md`](../src/uix/eidos/THEMING.md) §19
### 5. Validated token scope (TSC)
Where each token may be emitted is part of the source contract and validated at
generation, instead of ad-hoc CSS variables sprinkled across selectors. →
[`TSC.md`](../src/uix/eidos/TSC.md)
### 6. Graceful degradation
Components are headless-functional without a DOM, and sema is ornamental — sound
/ haptic / audio-disabled / SSR environments work without special-casing. →
[`testing-and-tooling.md`](./testing-and-tooling.md) (SSR posture)
## The honest trade-offs
- **More to learn.** Four layers + a perceptual vocabulary is more concepts than
"import a styled component." The [glossary](./glossary.md) and
[getting-started](./getting-started.md) exist because of this.
- **Smaller ecosystem.** Radix/Mantine have years of community components and
battle-testing; UIX is one codebase.
- **The perception layer only pays off if you use it.** A team that just wants
styled, accessible widgets gets the headless behavior — but the sema layer's
value (coherent sound/haptic/motion meaning) is realized only when an app
wires it.
## Where the per-component detail lives
Each component's `README.md` carries a `## Comparison` table against ark-ui,
bits-ui, radix-ui (and react-aria where relevant), with every gap marked and a
disposition (implement / defer / drop). That is the contract-level honesty;
this doc is the architecture-level one.

@ -39,6 +39,7 @@ permanente/efímero, drift, dos idiomas.
- **Fase 4 (3/3) — THEMING split (stubs)**: `THEMING.md` 2571→1930 L, partido renumber-safe en 3 docs-estrato: `eidos/TSC.md` (E2, §7+§18), `eidos/THEMING_GUIDE.md` (E4, §8+§9), `eidos/THEMING_NOTES.md` (E3, §15+§17). THEMING conserva stubs-puntero numerados → las 34 secciones y todas las citas `§N` del corpus/código sobreviven; §16 + `## Referencias` + §20-34 quedan in-place. Además §14 motion saneado (contradicción con eidos-motion.md). **Fase 4 cerrada.**
- **Fase 5 (1/n) — entrada E0**: nuevo `docs/README.md` — puerta única del corpus (lo pidió el usuario: "necesario para que los agentes empiecen y para cada sesión nueva"). Contiene: orientación de 60 seg, los 7 estratos, orden de lectura, mapa de docs por estrato (E1-E5 + process) y atajos task-oriented ("I want to…"). **Cableado desde `CLAUDE.md`** ("Start here", arriba de Reference Documents) para que toda sesión/agente lo lea primero. Todos los enlaces verificados. Pendiente del E0: solo adelgazar `CLAUDE.md` (ver Diferido).
- **Fase 5 (2/n) — glosario**: nuevo `docs/glossary.md` — el vocabulario inventado (las capas, morfo, soma, sema, eidos) definido en una línea cada término + puntero a la fuente autoritativa; el subset semántico (family/intent/verb/channel) **apunta a CANON, no se recopia** (sin drift). Enganchado en `docs/README.md` (estrato E0 + orden de lectura).
- **Fase 5 (6/n) — comparativa**: nuevo `docs/comparison.md` — posicionamiento honesto a nivel framework, anclado en los diferenciadores que el corpus YA documenta (morfo = contrato declarativo · sema = capa de percepción · motion de dos momentos · theme = retintar lo fijo · TSC · degradación headless/SSR) + los trade-offs reales (más que aprender · ecosistema menor · sema solo paga si la usas). NO inventa claims sobre competidores; la única concreta (Chakra colapsa presence en un eje) está sourced en eidos-motion.md. La comparativa per-componente sigue en los READMEs (doctrina). Enganchado en `docs/README.md`.
- **Fase 5 (5/n) — testing/tooling/codegen**: nuevo `docs/testing-and-tooling.md` — consolida la historia transversal de verificación (estaba dispersa en package.json / COMPONENT_GUIDE / SOMA_ARCHITECTURE): suite vitest de **2 proyectos** (client browser / server node), **validadores** (`morfo:check` · `morfo:vocabulary` · `component:audit` · `perm:check` · `smoke` · `translations:check` · eidos-lint — qué caza cada uno), **codegen** (`generate:eidos-css` · `generate:contracts-docs` + `compileMorfo`: generado vs autorado), y **postura SSR** (`dom:false`→disabledDom, ActiveDom owner-doc/iframe-safe, sema ornamental, hidratación = lo que `smoke` caza). Anclado en scripts reales de package.json. Enganchado en `docs/README.md` ("I want to… test").
- **Fase 5 (4/n) — getting-started**: nuevo `docs/getting-started.md` — el camino narrativo de cero a primer cambio: run it → modelo mental con la cadena de transcripción → **ver las 4 capas en un solo elemento del DOM** (toggle: `data-toggle`/`data-state`/`data-event-*` + el CSS de eidos) → loop de verificación con scripts reales → 3 caminos de primer cambio. Anclado en rutas reales (`/uix/components/*`, `/active`, `/temas`) y scripts reales (`check`/`test`/`morfo:check`/`smoke`/`component:audit`/`perm:check`); apunta a COMPONENT_GUIDE/THEMING_GUIDE sin duplicar. Enganchado en `docs/README.md` (callout arriba + fila "I want to"). Hay además un get-started de la app en `/active/get-started/*` (incl. ai-agents) — este es el doc-side.
- **Fase 5 (3/n) — reglas de autoría de doc**: nuevo `docs/authoring.md` — cómo se crea/edita documentación en el corpus, codificando lo que aprendió la migración: (1) linkear el canon, nunca copiarlo (la ley anti-drift); (2) cada doc tiene un estrato + dónde va; (3) docs de referencia atemporales (hand-offs/fechas/catálogos hardcoded → process o puntero); (4) una fuente por concern (roles distintos si hay 2 docs del mismo tema); (5) frontmatter; (6) ediciones renumber-safe (stub pattern para `§N` citadas, verificar links); (7) idioma EN; (8) naming `rfc-*`/`design-*`; + checklist pre-commit. Cada regla cita el fallo real que arregla. Enganchado en `docs/README.md` ("I want to… write a doc" + nota tras los estratos).
@ -55,7 +56,9 @@ permanente/efímero, drift, dos idiomas.
- **NOTA harness**: escribir un archivo EXISTENTE con PowerShell `Set-Content` o con regex (`\d+`, ` / ` sueltos) en el comando lo bloquea un analizador (lo lee como `Remove-Item path`). Funciona: `[System.IO.File]::WriteAllLines(abs, $arr, utf8NoBom)` + límites por `.StartsWith()` (sin regex). Crear archivos NUEVOS con `Set-Content` sí va. Las tools Edit/Write también.
### Fase 5 — huecos de libro (escribir nuevo)
~~Entrada E0~~ (hecho) · ~~Glosario~~ (hecho) · ~~reglas de autoría~~ (hecho) · ~~arco *getting-started*~~ (hecho) · decision-log consolidado (semilla: `src/docs/LIBRO_VARIACIONES_Y_EXTENSIONES.md`) · walkthrough "construye tu propia capa" · comparativa honesta vs Radix/Ark/Mantine (hoy dispersa en THEMING_NOTES §15, eidos-motion §16) · ~~historia transversal SSR/testing/codegen~~ (hecho).
~~Entrada E0~~ (hecho) · ~~Glosario~~ (hecho) · ~~reglas de autoría~~ (hecho) · ~~arco *getting-started*~~ (hecho) · decision-log consolidado (semilla: `src/docs/LIBRO_VARIACIONES_Y_EXTENSIONES.md`) · walkthrough "construye tu propia capa" · ~~comparativa honesta vs Radix/Ark/Mantine~~ (hecho) · ~~historia transversal SSR/testing/codegen~~ (hecho).
**Restan de Fase 5** (los más opinables/arriesgados): **decision-log consolidado** (riesgo: duplicar `LIBRO_VARIACIONES`, que YA es el decision-log impl-vs-libro; lo no-consolidado son los ~10 "Session hand-off" de CLAUDE.md → encaja mejor con el ítem Diferido "adelgazar CLAUDE.md") · **walkthrough "construye tu propia capa"** (especulativo — requiere validar que el patrón de capa se extiende limpio a una 5ª; mejor hacerlo deliberado, no de relleno).
### Diferido (decisión del usuario)
- **Rename físico de RFCs/design** (`*_ENGINE_RFC`/`*_RFC` → `rfc-*`; `DESIGN_CONN`/`DESIGN`/`DESIGN_TIMR` → `design-*`): los nombres actuales están citados como provenance en ~30 archivos de código (`eidos/lib/*.ts` ×~20, `arts/timer/*`, `arts/color/*`, `arts/session/types.ts`, tests) + ~10 docs + CLAUDE.md. `docs/decisions.md` ya da el naming consistente a nivel índice sin tocar nada. El rename físico solo vale la pena si se barren TODAS las citas en el mismo pass (si no, drift) — decisión del usuario por el coste/beneficio (cosmético vs ~40 archivos + `check`). De paso: ruta mala `soma/layers/GESTURES.md` (real: `layers/gesture/GESTURES.md`) en SOMA_ARCHITECTURE/old-README.

Loading…
Cancel
Save

Powered by TurnKey Linux.