You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/eidos/THEMING_NOTES.md

162 lines
6.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
title: Eidos Theming — Comparación + decisiones
type: notes
audience: human + agent
status: current
source: extracted from src/uix/eidos/THEMING.md (was §15 + §17)
---
# Eidos Theming — Comparación + decisiones
> Material E3 del theming: cómo se compara eidos con las librerías de referencia,
> y el FAQ de las decisiones polémicas (el porqué de las elecciones). Extraído de
> [`THEMING.md`](./THEMING.md) (referencia E1).
---
## Comparación con librerías de referencia
### Bundle size (app típica con 10 componentes)
| Sistema | Raw | Gzip | Strategy |
|---|---|---|---|
| Tailwind v4 | ~30 KB | ~10 KB | JIT atomic classes |
| **Eidos + purge** | **116 KB** | **13.6 KB** | **JIT custom-property purge** |
| Chakra Panda v3 | ~30 KB | ~12 KB | Build-time JIT |
| Mantine | ~60 KB | ~18 KB | Sin purge |
| Radix Themes | ~80 KB | ~22 KB | Sin purge |
| shadcn/ui | varía | varía | Copy-paste, no centralized |
| **Eidos sin purge** | **218 KB** | **25 KB** | Single CSS |
### Theming features
| Feature | Eidos | Radix Themes | Chakra Panda | Mantine | shadcn | Tailwind v4 |
|---|---|---|---|---|---|---|
| **Token scope as data** | ✅ TSC | ❌ implícito | ⚠️ build-time | ❌ runtime | ❌ N/A | ❌ N/A |
| **Auto-inferencia de deps** | ✅ `var()` parse | ❌ | ✅ types | ❌ | N/A | N/A |
| **Cross-axis collision** | ✅ explícito | ❌ | ⚠️ partial | ❌ | N/A | N/A |
| **Composite scopes** | ✅ `[axis:v, …]` | ❌ | ✅ conditional pairs | ❌ | N/A | N/A |
| **9 color roles canónicos** | ✅ libro | ⚠️ 6 accents | ❌ open | ❌ open | ⚠️ 4 roles | ❌ open |
| **6 size canon coordinated** | ✅ | ⚠️ 1-3 | ⚠️ 5 | ⚠️ 5 | ❌ | N/A |
| **Density runtime** | ✅ 3 levels | ❌ | ❌ | ⚠️ partial | ❌ | ❌ |
| **Contract introspection** | ✅ typed | ⚠️ docs | ✅ Panda | ⚠️ docs | ❌ | ❌ |
| **Runtime override** | ✅ contract-aware | ⚠️ via CSS vars | ❌ | ✅ CSSVarsProvider | ⚠️ via CSS | ❌ |
| **Persistence versioned** | ✅ envelope | ❌ | ❌ | ❌ | ❌ | N/A |
| **Perceptual layer (sema)** | ✅ unique | ❌ | ❌ | ❌ | ❌ | ❌ |
### Mental model
| Sistema | Token philosophy |
|---|---|
| Eidos | 7 layers de indirección, scope-as-contract, perceptual integration |
| Radix Themes | 3 layers, accent runtime swap, no scope contract |
| Chakra Panda | Conditional values build-time, recipe system |
| Mantine | Theme provider runtime, string interpolation |
| shadcn | Plano `--primary` + `.dark`, copy-paste components |
| Tailwind v4 | `@theme` directive, atomic utilities, no tokens compuestos |
**Lectura crítica**: Eidos NO es más simple que Tailwind ni más
ergonómico que shadcn. Es **más expresivo** en la dimensión "qué
puede comunicar un componente". Si tu app solo necesita un color
primario y un dark mode, shadcn es la respuesta. Si tu app necesita
diferenciar perceptualmente entre "guardar borrador" (affirm) y
"borrar permanentemente" (loss) con tokens y animaciones distintas,
Eidos es el sistema.
---
## FAQ — decisiones polémicas
### ¿Por qué el theming no vive en Morfo? ¿No debería Morfo ser source of truth de todo?
Pregunta CRÍTICA — respuesta detallada en [sección 1.bis](#1bis-theming-vive-en-eidos-no-en-morfo-por-diseño).
Resumen: morfo es source-of-truth del **contrato cross-layer** (parts,
events, attrs, archetypes, attr values). Tokens/themes/recipes pertenecen
a Eidos por diseño explícito de la arquitectura (`active_architecture.md`
§9). La regla 2-de-3 lo deriva: los tokens visuales los consume solo
eidos → 1-de-3 → no entra en morfo. La integración eidos↔morfo se hace
**a través del DOM** (los recipes targetean attrs que morfo declara), NO
importando objetos morfo en TS (la regla #6 lo prohíbe explícitamente).
### ¿Por qué 7 capas de indirección? Parece excesivo
Cada capa sirve un override point real:
- Sin capa 1, no puedes traer una paleta Radix custom.
- Sin capa 2, no puedes remapear roles.
- Sin capa 3, no puedes ajustar slots per role.
- Sin capa 4, no puedes overridear un color SOLO para un componente.
- Sin capa 5, no puedes tener palette dinámico por instancia.
- Sin capa 6, no puedes combinar variant × palette.
- Sin capa 7, los recipes mezclan tokens externos con internos.
La capa 4 es la más sospechosa de redundancia. Es candidata a
deprecate si después de 6 meses ningún consumer la usa.
### ¿Por qué TSC y no simplemente convención?
**Convención falla en silencio**. El bug del Toggle (pre-TSC) habría
quedado escondido años. Con TSC, el build falla. Es la diferencia
entre "deberías hacerlo bien" y "no puedes hacerlo mal".
### ¿Por qué no usar Tailwind si es más pequeño?
Tailwind:
- No tiene roles semánticos canónicos (success/danger/warning sí pero
son del mundo Bootstrap).
- No tiene perceptual layer (sema).
- No tiene density runtime.
- No tiene contract introspection programática.
Pero si tu app es simple, **úsalo**. Eidos justifica su complejidad
sólo cuando la app necesita las dimensiones que Eidos cubre.
### ¿Por qué no atomic classes como Tailwind?
Custom properties permiten:
- **Cascada dinámica** (palette overrides en runtime).
- **Theme switching** sin recompile.
- **Persistencia** del user's theme.
- **Composability** con sema (`event:*` scope).
Atomic classes son más comprimibles pero son estáticas. Imposible
hacer `--palette-solid` cambie con `data-color='affirm'` desde
atomic classes sin generar ×N variantes en build.
### ¿Por qué inventar "TSC" y no usar @scope nativo de CSS?
`@scope` (CSS Cascading Modules L6) es bleeding-edge: Chrome 118+,
Firefox 128+, Safari aún no. No es production-ready 2026.
Cuando @scope sea universal, TSC podría re-implementarse encima de
él. La superficie del config (declarations[] + scope) seguiría igual;
sólo cambiaría el CSS emitido.
### ¿Por qué `event:` en TSC y no usar el `data-motion-ref` del doc motion?
Tres razones:
1. **TSC ya existe y funciona**. `data-motion-ref` requeriría un
atributo DOM nuevo, runtime para inyectarlo, registry separado.
2. **Sema ya emite `data-event`**. Reutilizar es 0 coste arquitectónico.
3. **Composable**: `scope: ['event:announce', 'color:affirm']` permite
diferenciar la animación según valencia. `data-motion-ref` perdería
eso o requeriría keys más complejas.
### ¿Cuál es el siguiente paso?
Pendientes deferred:
- Migrar los 5 palette consumers (button, checkbox, switch, radio-group,
toggle-group) a `declarations[]` para uniformidad.
- Implementar el primer caso real de `scope: 'event:*'` (e.g. toast
bg-during-announce).
- Decidir si colapsar la capa 4 (component-color) — defer hasta que
un consumer pida ese punto de extensión.
---

Powered by TurnKey Linux.