9.1 KiB
tree-view — alcance de tema: análisis y propuesta
Generado por
node --import tsx/esm scripts/theming-census.ts --report. Lo medido y la propuesta se regeneran; el Veredicto (§5) se conserva. Vista de conjunto: README · método y protocolo:PLAN-theming.md§1, §2, §7.
- Medido: 2026-08-23 · Alcance: 92% — 24 de 26 knobs por token público
- Knobs de apariencia: 28 — público 24 · privado 1 · global 0 · literal 1 · sistema 2 · excepción 0 (los dos últimos, fuera del ratio)
- Contrato hoy (
lib/recipes/base.ts): 46 pública(s) —row-height-xs,row-height-sm,row-height-md,row-height-lg,row-height-xl,row-padding-block-xs,row-padding-block-sm,row-padding-block-md,row-padding-block-lg,row-padding-block-xl,row-padding-inline-xs,row-padding-inline-sm,row-padding-inline-md,row-padding-inline-lg,row-padding-inline-xl,indent-xs,indent-sm,indent-md,indent-lg,indent-xl,font-size-xs,font-size-sm,font-size-md,font-size-lg,font-size-xl,row-height,row-padding-block,row-padding-inline,indent,font-size,radius,font-family,line-height,fg,border-width,border,surface-bg,padding,row-gap,row-radius,hover-row-bg,disabled-row-fg,branch-indicator-size,branch-indicator-fg,guide-width,guide-fg· 1 privada(s) forward —_palette-element - Eje
size: no · ficheros:tree-view.css
1. Knobs fuera de alcance
1.1 Directo a primitivo global (0)
Ninguno.
1.2 A través de un privado (1)
| # | fichero:línea | selector | propiedad | valor |
|---|---|---|---|---|
| 1 | tree-view.css:115 |
[data-tree-view-branch-control][data-selected]:not([data-disabled]), [data-tree-view-item][data-selected]:not([data-disabled]) |
background |
var(--_tree-view-palette-element) |
1.3 Literales (1)
| # | fichero:línea | selector | propiedad | valor |
|---|---|---|---|---|
| 1 | tree-view.css:38 |
[data-tree-view-root][data-block] |
inline-size |
100% |
1.4 Excepciones firmadas (0) — fuera del ratio
Literales que llevan su anotación /* literal: <razón> */ en la propia
declaración: la válvula de recipe-contract §3, la misma que honra
component-audit. Una desviación firmada no es deuda — se listan para que la
razón se lea, no para acuñarlas.
Ninguno.
2. Sistema transversal (2) — informativo, fuera del ratio
Un tema los alcanza a nivel de sistema, por diseño (recipe-contract §2).
| # | fichero:línea | selector | propiedad | valor |
|---|---|---|---|---|
| 1 | tree-view.css:122 |
[data-tree-view-branch-control][data-disabled], [data-tree-view-item][data-disabled] |
opacity |
var(--opacity-disabled) |
| 2 | tree-view.css:127 |
[data-tree-view-branch-control]:focus-visible, [data-tree-view-item]:focus-visible |
outline |
var(--focus-ring-width) solid var(--focus-ring-color) |
3. Privados de la receta — ¿de dónde sale su valor?
La receta no declara privados propios en su CSS.
Consumidos y no declarados en el CSS (vienen de base.ts o de un estilo inline del wrapper): --_tree-view-palette-element.
4. Propuesta de corrección
4.1 Tokens a declarar en lib/recipes/base.ts (0)
Valor verbatim del CSS de hoy: el default no se mueve, sólo cambia quién
puede moverlo. Nombres derivados de recipe-contract §1 (ejes lógicos, talla
al final) y theming §6.7 (slots de color, modificador delante). Un token con
DOS valores distintos es una colisión de nombre: son dos knobs, o el nombre
no distingue lo que debería — se marca ⚠.
token (--tree-view-…) |
scope TSC | valor propuesto | usos |
|---|
4.2 Sin nombre mecánico (2)
- ⚠ decisión:
100%es un valor identidad o geometría de layout, no un knob de tema — el perímetro de «knob» es D-TH.2, sin firmar — 1:inline-size. - ⚠ decisión: el privado que alimenta este knob no se declara en el CSS (viene de
base.tso de un estilo inline) — hay que resolverlo antes de nombrarlo — 1:background.
4.4 Lo que hay que comprobar a mano (PLAN-theming §1.3 · §7.4)
- Privado que no deriva de un público — §3 lo marca; el privado debe leer el público o desaparecer.
- Velo o acento en el nodo equivocado (
archetype: 'item'en un envoltorio, unbackgrounden shorthand que mata la capa de estado) — se mide desde el píxel hacia arriba. - Doble animación al mover un sello a una superficie con animación propia — registro de
animationstart/animationend. - Diff de computed = 0 en reposo · hover · abierto · disabled · foco, por talla, antes y después.
- Centinela por token nuevo: valor imposible en el root → el nodo lo sigue. Si no, el token miente.
5. Veredicto
Medido 2026-08-21. La §4 propone 30 tokens y falla en el nombre de casi
todos los que importan: el clasificador tomó el PRIMER selector de cada regla
como si fuera la parte pintada, y aquí ese primer selector es el root o el
branch-control cuando el nodo real es otro. Corregido queda en 46 claves, con
el molde del hermano tree-grid allí donde el problema es el mismo.
root-width: 1pxyroot-bg: var(--color-border-default)NO son del root: son la GUÍA de indentación. El selector es[data-tree-view-root][data-indent-guides] [data-tree-view-branch]::beforey lo pintado es el pseudo del branch. Nombres correctosguide-width+guide-fg, literalmente los detree-grid. Unroot-bgque en realidad tiñe una línea vertical es la clase de nombre que miente.branch-control-padding-inline-{k}⚠ funde DOS ejes distintos: el ritmo de la fila (--_tree-view-row-padding-inline, space-1/2/2/3/4) y el PASO DE PROFUNDIDAD (--_tree-view-indent, space-3/3/4/5/6), que se multiplican en el mismocalc. →row-padding-inline-{k}+indent-{k}, comotree-grid. Fundirlos habría hecho imposible tematizar la sangría sin mover el padding.- El prefijo
branch-control-es erróneo: el knob es de la FILA. Las reglas rezan[data-tree-view-branch-control], [data-tree-view-item]— las dos filas del árbol. El propio CSS ya llamarowa sus privados. →row-*, coherente contree-gridy con la lección detable(«el valor es la altura de la FILA, no del root»). Y fuera el prefijoroot-del chasis: el wrapper ES el componente (mismo criterio quetree-grid). row-padding-block⚠ es POR TALLA, no dos valores en pugna: xs vale0y las otras cuatro--space-1. Cinco coordenadas.branch-indicator-width+-heightson UN knob (1emlos dos) →branch-indicator-size. Mismo caso que el checkbox degrid-list.- Los shorthand se parten:
borderde surface/outline/ghost → unborder-width+ unborder(color);paddingde surface/outline →padding. Lostransparentde ghost/outline y elpadding: 0de ghost son IDENTIDAD de variante y se quedan literales, igual que el100%de[data-block]. - La tipografía va un paso por debajo desde md (xs→xs, sm→sm, md→sm,
lg→md, xl→lg) — el patrón exacto de
tableytree-grid, verbatim, no se «corrige» al 1:1. La altura de fila SÍ es 1:1 con el bundle. Los resueltos llevanparts: ['root']:data-sizese estampa en[data-tree-view-root], que es wrapper de eidos y no parte del morfo (precedentetree-grid). hover-row-bgSÍ se acuña — al revés que engrid-list, y por medición. La regla cubre dos nodos con arquetipo distinto:branch-controlno lleva archetype, así que ahí el plano de la receta es la ÚNICA pintura (velo ausente:background-image: nonemedido), y el token es la única superficie de tema del hover. En[data-tree-view-item](que sí esitem) se le suma el velo encima, pero el token sigue moviendo el plano de debajo. Tener un consumidor legítimo es lo que lo distingue del casogrid-list, donde no tenía ninguno.
⚠ El defecto que la medición destapó — el velo DERRAMA sobre el subárbol
Al pasar el ratón por la fila de una carpeta abierta se tiñe la carpeta
entera, hijos incluidos: capturado sobre src, el nodo velado mide 336 px
(la rama completa) en vez de los 36 px de la fila. La causa es que
archetype: 'item' está declarado en el <li> branch
(morfo/components/tree-view.ts:103), que contiene el control Y el
branch-content con todo el subárbol, mientras la fila que el usuario señala
es el branch-control de dentro. Un branch anidado acumula además el velo de
sus ancestros: en la captura, lib se ve más oscuro que sus hermanos por
llevar dos.
Es PREEXISTENTE (nada que ver con la tokenización), mueve píxel y mover el
arquetipo es morfo: se mide, se anota en next-features.md §12 y se sigue.
Es la tercera variante de la misma familia — table lo tiene en fila Y celda,
grid-list en fila Y celda sobre el mismo nodo, y tree-view en un ANCESTRO
del nodo señalado.