19 KiB
Auditoría de alcance de tema — el catálogo entero
Generado, no escrito a mano:
node --import tsx/esm scripts/theming-census.ts --report. Este README es la vista de conjunto; una ficha por componente al lado, con su análisis y su propuesta de corrección. Método, clases, protocolo de verificación y fases:PLAN-theming.md. La auditoría del SISTEMA de theming (fase 1, cerrada 2026-07-07) estheming-audit.md; ésta es la deuda de adopción que aquélla dejó apuntada en su §5.3-3.
- Medido: 2026-08-23 · 162 recetas con CSS + 8 componentes sin receta = 170 fichas, el árbol entero de
eidos/components/ - La pregunta: ¿cuánto de la apariencia de cada componente puede cambiar un tema sin tocar el sistema ni la receta?
- Alcance global: 66% — 3034 de 4581 knobs pasan por un token público del componente
- Reparto: público 3034 · privado 317 · global 827 · literal 403 · sistema transversal 509 · excepción firmada 128 (los dos últimos, fuera del ratio)
- Sin token público propio: 24 · alcance < 20 %: 12 · alcance 100 %: 27 · con eje
size: 57
Cómo se lee
| clase | qué es | ¿lo alcanza un tema del componente? |
|---|---|---|
public |
var(--{c}-…), el contrato del componente |
sí |
private |
var(--_{c}-…), nombre interno |
sólo si el privado deriva de un público (cada ficha lo dice en §3) |
global |
primitivo del sistema (--space-*, --radius-*, --color-*, bundle --size-{k}-*…) |
sólo moviendo el sistema entero |
literal |
ni token: 8px, 1.25, #fff |
no — y viola R-2/R-4 |
system |
sistemas transversales que la receta CONSUME por contrato (capa de estado, anillo de foco, planos de depth, motion, bandas z, opacidad, shape, floating-gap) | sí, a nivel de sistema, por diseño (recipe-contract §2) — fuera del ratio |
exception |
un literal con su anotación /* literal: <razón> */ en la propia declaración |
no hace falta: es la válvula de recipe-contract §3, una desviación ya firmada — fuera del ratio |
Alcance = public / (public + private + global + literal). system y exception
quedan fuera del denominador: el primero es tematizable a nivel de sistema por
diseño, el segundo es una desviación que el canon ya aceptó por escrito.
Límites de la medida (regex sobre el CSS; sobre-reporta, nunca infra-reporta):
una declaración con varios tokens se clasifica por la primera clase que casa
(público → privado → sistema → global); el token público de OTRO componente
cuenta como global y la ficha lo marca «⤴ prestado»; los valores dentro de
@keyframes cuentan como cualquier otro. Tres defectos que ningún regex ve —
privado que no deriva, velo en el nodo equivocado, doble animación — van en la
checklist §4.4 de cada ficha.
Qué NO propone una ficha
La propuesta deriva nombres de la doctrina; no la contradice. Por eso una ficha nunca propone acuñar un token para:
- lo que posee una capa compartida (
list-surface,spin-field,picker-shell,viewport-placement,field-segment-state,menu-indicator,sliding-indicator): un eje = un token público de la capa- una ranura privada, consumido
var(--_x, var(--x))— el consumidor no acuña--{c}-{eje}(README deeidos/components, «Capas compartidas» regla 2);
- una ranura privada, consumido
- el foco (
--focus-ring-*, theming §32) ni la capa de estado (--state-*, §38): un knob del sistema, no del componente; - un token prestado de otro componente (la familia
calendaren los pickers): la corrección es la decisión de familia registrada entheming-audit.md§B, no un duplicado con prefijo propio; - un shorthand o un eje físico (
padding,border,height): primero se parte en ejes lógicos (recipe-contract §1, R-4.4), y eso es decisión.
Sin receta CSS (8)
Ni un .css en su directorio: no hay knob que medir, y eso es una
respuesta, no un hueco. Cada ficha dice —medido, no supuesto— dónde vive su
visual: el componente que compone, la capa compartida que consume, o la receta
ajena que pinta sus attrs (y cuyos knobs ya están contados allí).
affix · count-up · format-date · format-number · icon-button · relative-time · svg · trans
Y el vocabulario de nombres tiene una desviación medida: el catálogo habla
mayoritariamente con el modificador al final (-bg-hover, -bg-active) mientras
theming §6.7 lo pone delante (hover-bg). Las fichas proponen la forma
documentada y lo dejan anotado: la normalización es D-TH.6, sin firmar.
Los 20 con más knobs fuera del contrato
| # | componente | fuera de alcance | alcance | knobs | contrato |
|---|---|---|---|---|---|
| 1 | palabras | 360 | 22% | 468 | 0 |
| 2 | chronos | 234 | 1% | 244 | 9 |
| 3 | time-range-picker | 67 | 20% | 88 | 22 |
| 4 | proof-of-human | 61 | 19% | 79 | 20 |
| 5 | time-picker | 47 | 18% | 59 | 16 |
| 6 | field-langs | 37 | 0% | 39 | 0 |
| 7 | date-range-picker | 30 | 40% | 53 | 22 |
| 8 | drawer | 29 | 60% | 74 | 54 |
| 9 | radio-cards | 27 | 61% | 72 | 40 |
| 10 | color-picker | 20 | 75% | 82 | 71 |
| 11 | natural-time-picker | 20 | 74% | 77 | 62 |
| 12 | sidebar | 19 | 55% | 45 | 50 |
| 13 | mockup | 18 | 38% | 29 | 0 |
| 14 | radio-group | 17 | 77% | 75 | 61 |
| 15 | popover | 16 | 67% | 51 | 46 |
| 16 | form | 15 | 71% | 52 | 54 |
| 17 | tag-group | 15 | 65% | 46 | 91 |
| 18 | file-upload | 14 | 76% | 61 | 98 |
| 19 | combobox | 13 | 85% | 97 | 106 |
| 20 | password-field | 13 | 62% | 35 | 30 |
Sin ningún token público propio (24)
Ni una clave pública en lib/recipes/base.ts — alguno tiene privados forward
(_palette-*), que no son contrato: un tema no puede nombrarlos.
alert-dialog · aspect-ratio · auto-grid · avatar · cascade · css-field · date-picker · display · field-langs · heading · highlight · mask-field · mockup · month-grid · motion · number-field · palabras · range-calendar · stack · text · text-blur · text-scramble · wrap · year-grid
Tabla completa (162 recetas, por alcance ascendente)
La columna «contrato» cuenta las claves públicas del bloque del componente.
| componente | alcance | knobs | público | privado | global | literal | sistema | contrato | size |
|---|---|---|---|---|---|---|---|---|---|
| range-calendar | 0% | 98 | 0 | 7 | 2 | 4 | 85 | 0 | – |
| month-grid | 0% | 61 | 0 | 7 | 0 | 5 | 49 | 0 | – |
| year-grid | 0% | 61 | 0 | 7 | 0 | 5 | 49 | 0 | – |
| field-langs | 0% | 39 | 0 | 0 | 31 | 6 | 2 | 0 | – |
| aspect-ratio | 0% | 3 | 0 | 0 | 1 | 2 | 0 | 0 | – |
| date-picker | 0% | 2 | 0 | 0 | 0 | 2 | 0 | 0 | – |
| text-blur | 0% | 2 | 0 | 0 | 0 | 2 | 0 | 0 | – |
| cascade | 0% | 1 | 0 | 0 | 0 | 1 | 0 | 0 | – |
| motion | 0% | 1 | 0 | 0 | 0 | 1 | 0 | 0 | – |
| chronos | 1% | 244 | 3 | 21 | 202 | 11 | 7 | 9 | y |
| time-picker | 18% | 59 | 10 | 12 | 24 | 11 | 2 | 16 | y |
| proof-of-human | 19% | 79 | 14 | 17 | 29 | 15 | 4 | 20 | – |
| time-range-picker | 20% | 88 | 17 | 19 | 33 | 15 | 4 | 22 | y |
| skin-media-player | 22% | 11 | 2 | 0 | 1 | 6 | 2 | 10 | y |
| palabras | 22% | 468 | 103 | 1 | 272 | 87 | 5 | 0 | – |
| surface | 25% | 4 | 1 | 3 | 0 | 0 | 0 | 25 | – |
| scroll-frames | 33% | 9 | 3 | 1 | 1 | 4 | 0 | 4 | – |
| link | 36% | 14 | 4 | 4 | 1 | 2 | 3 | 5 | – |
| menu-dial | 38% | 8 | 3 | 0 | 1 | 4 | 0 | 3 | y |
| mockup | 38% | 29 | 11 | 0 | 13 | 5 | 0 | 0 | – |
| date-range-picker | 40% | 53 | 20 | 9 | 19 | 2 | 3 | 22 | y |
| skeleton | 45% | 11 | 5 | 5 | 0 | 1 | 0 | 9 | – |
| text-scramble | 50% | 4 | 2 | 0 | 0 | 2 | 0 | 0 | – |
| split-button | 50% | 2 | 1 | 0 | 1 | 0 | 0 | 1 | y |
| toggle-group | 50% | 2 | 1 | 0 | 1 | 0 | 0 | 1 | – |
| sidebar | 55% | 45 | 23 | 0 | 14 | 5 | 3 | 50 | – |
| audio-player | 56% | 18 | 10 | 0 | 8 | 0 | 0 | 8 | – |
| drawer | 60% | 74 | 43 | 8 | 16 | 5 | 2 | 54 | y |
| mark | 60% | 5 | 3 | 2 | 0 | 0 | 0 | 3 | – |
| radio-cards | 61% | 72 | 43 | 0 | 23 | 4 | 2 | 40 | y |
| password-field | 62% | 35 | 21 | 2 | 2 | 9 | 1 | 30 | y |
| clipboard | 63% | 8 | 5 | 2 | 1 | 0 | 0 | 6 | – |
| spin-field | 64% | 27 | 16 | 0 | 8 | 1 | 2 | 20 | – |
| spinner | 64% | 25 | 16 | 5 | 0 | 4 | 0 | 18 | – |
| meter | 64% | 14 | 9 | 1 | 2 | 2 | 0 | 28 | y |
| pin-input | 65% | 18 | 11 | 0 | 6 | 0 | 1 | 20 | y |
| tag-group | 65% | 46 | 28 | 14 | 0 | 1 | 3 | 91 | y |
| popover | 67% | 51 | 32 | 4 | 12 | 0 | 3 | 46 | y |
| dialog | 67% | 36 | 24 | 4 | 7 | 1 | 0 | 37 | y |
| image-adjustments | 67% | 18 | 10 | 0 | 4 | 1 | 3 | 12 | – |
| virtual-list | 67% | 13 | 8 | 0 | 0 | 4 | 1 | 12 | – |
| separator | 67% | 6 | 4 | 0 | 0 | 2 | 0 | 3 | – |
| listbox | 68% | 37 | 23 | 9 | 1 | 1 | 3 | 21 | – |
| progress | 69% | 35 | 24 | 2 | 3 | 6 | 0 | 41 | y |
| color-swatch | 70% | 10 | 7 | 0 | 3 | 0 | 0 | 12 | y |
| s-text-virtual-list | 70% | 10 | 7 | 0 | 3 | 0 | 0 | 9 | – |
| form | 71% | 52 | 36 | 8 | 5 | 2 | 1 | 54 | y |
| image-picker | 71% | 20 | 12 | 0 | 1 | 4 | 3 | 13 | – |
| search-field | 71% | 15 | 10 | 0 | 0 | 4 | 1 | 17 | y |
| skip-link | 71% | 8 | 5 | 0 | 0 | 2 | 1 | 8 | – |
| checkbox | 72% | 30 | 21 | 8 | 0 | 0 | 1 | 47 | y |
| virtual-grid | 73% | 12 | 8 | 0 | 0 | 3 | 1 | 12 | – |
| natural-time-picker | 74% | 77 | 56 | 0 | 14 | 6 | 1 | 62 | y |
| color-picker | 75% | 82 | 59 | 7 | 2 | 11 | 3 | 71 | y |
| editable | 75% | 44 | 30 | 7 | 1 | 2 | 4 | 56 | y |
| avatar | 75% | 36 | 27 | 3 | 0 | 6 | 0 | 0 | y |
| tooltip | 75% | 21 | 15 | 5 | 0 | 0 | 1 | 23 | y |
| badge | 75% | 20 | 15 | 5 | 0 | 0 | 0 | 71 | y |
| switch | 76% | 22 | 16 | 4 | 1 | 0 | 1 | 51 | y |
| file-upload | 76% | 61 | 45 | 9 | 1 | 4 | 2 | 98 | y |
| timeline | 77% | 47 | 36 | 10 | 0 | 1 | 0 | 45 | y |
| carousel | 77% | 35 | 23 | 2 | 0 | 5 | 5 | 27 | – |
| radio-group | 77% | 75 | 56 | 10 | 7 | 0 | 2 | 61 | y |
| chat-log | 77% | 42 | 30 | 0 | 4 | 5 | 3 | 31 | – |
| card | 78% | 37 | 28 | 8 | 0 | 0 | 1 | 97 | y |
| knob | 78% | 26 | 18 | 1 | 1 | 3 | 3 | 33 | – |
| stepper | 79% | 60 | 44 | 11 | 0 | 1 | 4 | 69 | y |
| callout | 79% | 14 | 11 | 3 | 0 | 0 | 0 | 34 | – |
| chat-composer | 79% | 44 | 31 | 0 | 3 | 5 | 5 | 31 | – |
| aura | 80% | 35 | 28 | 0 | 1 | 6 | 0 | 37 | y |
| textarea | 80% | 28 | 20 | 2 | 0 | 3 | 3 | 37 | – |
| rating-group | 80% | 16 | 12 | 0 | 1 | 2 | 1 | 25 | y |
| toggle | 81% | 28 | 22 | 1 | 1 | 3 | 1 | 119 | y |
| code-block | 81% | 27 | 22 | 2 | 3 | 0 | 0 | 20 | – |
| metrics | 82% | 50 | 41 | 5 | 0 | 4 | 0 | 72 | y |
| prose | 83% | 53 | 44 | 0 | 0 | 9 | 0 | 37 | y |
| select | 83% | 72 | 54 | 5 | 3 | 3 | 7 | 101 | y |
| float-panel | 84% | 53 | 41 | 3 | 0 | 5 | 4 | 40 | – |
| calendar | 84% | 71 | 57 | 7 | 0 | 4 | 3 | 74 | – |
| onion-menu | 84% | 22 | 16 | 0 | 1 | 2 | 3 | 19 | – |
| chat-message | 84% | 84 | 65 | 0 | 6 | 6 | 7 | 75 | y |
| grid-list | 85% | 31 | 22 | 2 | 1 | 1 | 5 | 38 | – |
| combobox | 85% | 97 | 76 | 4 | 3 | 6 | 8 | 106 | – |
| waveform | 86% | 7 | 6 | 0 | 1 | 0 | 0 | 11 | y |
| table | 86% | 46 | 37 | 3 | 0 | 3 | 3 | 45 | – |
| context-menu | 87% | 33 | 26 | 0 | 1 | 3 | 3 | 28 | – |
| kbd | 87% | 15 | 13 | 0 | 1 | 1 | 0 | 13 | – |
| fab | 88% | 16 | 14 | 0 | 2 | 0 | 0 | 10 | – |
| announce | 88% | 8 | 7 | 0 | 1 | 0 | 0 | 9 | – |
| media-player | 88% | 50 | 44 | 0 | 0 | 6 | 0 | 61 | – |
| tags-input | 88% | 46 | 37 | 4 | 1 | 0 | 4 | 90 | y |
| gradient-picker | 88% | 27 | 23 | 0 | 2 | 1 | 1 | 25 | – |
| menubar | 88% | 27 | 23 | 0 | 3 | 0 | 1 | 35 | y |
| drag-drop | 89% | 16 | 8 | 1 | 0 | 0 | 7 | 9 | – |
| chat-typing | 89% | 9 | 8 | 0 | 1 | 0 | 0 | 7 | – |
| chart | 89% | 95 | 81 | 0 | 0 | 10 | 4 | 45 | – |
| card-group | 90% | 22 | 18 | 0 | 0 | 2 | 2 | 20 | – |
| collapsible | 90% | 12 | 9 | 0 | 1 | 0 | 2 | 11 | – |
| result | 90% | 21 | 19 | 0 | 0 | 2 | 0 | 27 | – |
| accordion | 91% | 65 | 58 | 1 | 0 | 5 | 1 | 76 | y |
| toolbar | 91% | 35 | 30 | 2 | 0 | 1 | 2 | 54 | y |
| feed | 91% | 34 | 30 | 1 | 1 | 1 | 1 | 50 | – |
| button | 91% | 23 | 20 | 2 | 0 | 0 | 1 | 106 | y |
| tree-view | 92% | 28 | 24 | 1 | 0 | 1 | 2 | 46 | – |
| gradient-builder | 93% | 60 | 52 | 0 | 1 | 3 | 4 | 72 | – |
| color-field | 93% | 15 | 14 | 0 | 1 | 0 | 0 | 26 | y |
| scroll-area | 94% | 17 | 15 | 0 | 0 | 1 | 1 | 13 | – |
| cropper | 94% | 20 | 17 | 0 | 1 | 0 | 2 | 17 | – |
| tree-grid | 95% | 42 | 37 | 1 | 0 | 1 | 3 | 47 | – |
| background | 95% | 23 | 19 | 1 | 0 | 0 | 3 | 37 | – |
| picker-shell | 95% | 21 | 20 | 0 | 1 | 0 | 0 | 31 | y |
| nav-tree | 96% | 24 | 22 | 0 | 0 | 1 | 1 | 18 | – |
| image | 96% | 23 | 22 | 1 | 0 | 0 | 0 | 23 | y |
| tabs | 96% | 78 | 74 | 0 | 2 | 1 | 1 | 79 | y |
| dropdown-menu | 96% | 30 | 27 | 0 | 1 | 0 | 2 | 28 | – |
| slider | 97% | 33 | 31 | 0 | 0 | 1 | 1 | 39 | y |
| toast | 98% | 46 | 45 | 0 | 0 | 1 | 0 | 85 | – |
| command | 98% | 52 | 49 | 0 | 0 | 1 | 2 | 57 | – |
| field | 98% | 64 | 58 | 1 | 0 | 0 | 5 | 68 | y |
| navigation-menu | 100% | 37 | 33 | 0 | 0 | 0 | 4 | 44 | – |
| heading | — | 36 | 0 | 0 | 0 | 0 | 36 | 0 | – |
| s-text | 100% | 30 | 2 | 0 | 0 | 0 | 28 | 3 | – |
| emoji-picker | 100% | 26 | 22 | 0 | 0 | 0 | 4 | 21 | – |
| pagination | 100% | 26 | 24 | 0 | 0 | 0 | 2 | 34 | y |
| text | — | 24 | 0 | 0 | 0 | 0 | 24 | 0 | – |
| breadcrumb | 100% | 23 | 20 | 0 | 0 | 0 | 3 | 28 | y |
| chat-list | 100% | 18 | 18 | 0 | 0 | 0 | 0 | 18 | – |
| splitter | 100% | 18 | 17 | 0 | 0 | 0 | 1 | 15 | – |
| empty-state | 100% | 17 | 17 | 0 | 0 | 0 | 0 | 26 | y |
| link-preview | 100% | 17 | 14 | 0 | 0 | 0 | 3 | 35 | – |
| code | 100% | 13 | 7 | 0 | 0 | 0 | 6 | 6 | – |
| anchor-nav | 100% | 12 | 11 | 0 | 0 | 0 | 1 | 12 | – |
| date-field | 100% | 11 | 11 | 0 | 0 | 0 | 0 | 21 | y |
| time-field | 100% | 11 | 11 | 0 | 0 | 0 | 0 | 21 | y |
| text-gradient | 100% | 10 | 10 | 0 | 0 | 0 | 0 | 7 | – |
| banner | 100% | 9 | 9 | 0 | 0 | 0 | 0 | 53 | y |
| box | 100% | 9 | 9 | 0 | 0 | 0 | 0 | 43 | – |
| label | 100% | 8 | 2 | 0 | 0 | 0 | 6 | 2 | – |
| text-focus | 100% | 8 | 8 | 0 | 0 | 0 | 0 | 8 | – |
| date-range-field | 100% | 7 | 6 | 0 | 0 | 0 | 1 | 7 | – |
| time-range-field | 100% | 7 | 6 | 0 | 0 | 0 | 1 | 7 | – |
| display | — | 6 | 0 | 0 | 0 | 0 | 6 | 0 | – |
| text-circular | 100% | 6 | 6 | 0 | 0 | 0 | 0 | 6 | – |
| barcode | 100% | 5 | 5 | 0 | 0 | 0 | 0 | 7 | – |
| qr-code | 100% | 3 | 3 | 0 | 0 | 0 | 0 | 10 | – |
| button-group | 100% | 2 | 2 | 0 | 0 | 0 | 0 | 1 | – |
| flex | 100% | 2 | 2 | 0 | 0 | 0 | 0 | 7 | – |
| grid | 100% | 2 | 2 | 0 | 0 | 0 | 0 | 13 | – |
| sticky | 100% | 1 | 1 | 0 | 0 | 0 | 0 | 1 | – |
| alert-dialog | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| auto-grid | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| container | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
| css-field | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| float | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
| group | — | 0 | 0 | 0 | 0 | 0 | 0 | 1 | – |
| highlight | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| icon | — | 0 | 0 | 0 | 0 | 0 | 0 | 2 | – |
| mask-field | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| number-field | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| section | — | 0 | 0 | 0 | 0 | 0 | 0 | 4 | – |
| stack | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
| wrap | — | 0 | 0 | 0 | 0 | 0 | 0 | 0 | – |
Veredicto y decisiones
(pendiente — lo escribe el autor; se conserva al regenerar)