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/docs/audit/theming/tree-view.md

164 lines
9.7 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.

# 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](./README.md) · método y protocolo:
> [`PLAN-theming.md`](../../process/PLAN-theming.md) §1, §2, §7.
- **Medido**: 2026-08-25 · **Alcance**: **96%** — 24 de 25 knobs por token público
- **Knobs de apariencia**: 28 — público 24 · privado 0 · global 0 · literal 1 · sistema 2 · excepción 0 · estructural 0 · puente 1 · canal 0 _(los cinco ú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 (0)
Sólo el **residuo**: el puente de paleta (§2-ter) y el canal de valor
(§2-quater) salen aparte, porque no son deuda ni tienen nombre que acuñar.
_Ninguno._
### 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)` |
## 2-ter. Puente de paleta THM-2 (1) — fuera del ratio
La receta lee `var(--_tree-view-palette-{slot})`, que **lo escribe el forward** de la
cascada de paleta bajo `[data-tree-view]:where([data-color], [data-color-custom])`
(`renderRecipePaletteForward`, firma B′). Es el MECANISMO de la paleta por
instancia, y se alcanza **dos veces**: por la capa compartida `--palette-*` y
por los tonos públicos del propio componente. **No se acuña**: un público
encima dejaría que un tema lo fijara y matara en silencio el `color=` de cada
instancia (veredictos §5 de `card`, `tags-input`, `avatar`).
| # | 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)` |
## 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 (1)
- **⚠ 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`.
### 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, un `background` en 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
<!-- veredicto:start -->
**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.
1. **`root-width: 1px` y `root-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]::before`
y lo pintado es el pseudo del branch. Nombres correctos **`guide-width` +
`guide-fg`**, literalmente los de `tree-grid`. Un `root-bg` que en realidad
tiñe una línea vertical es la clase de nombre que miente.
2. **`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 mismo `calc`. → `row-padding-inline-{k}` + `indent-{k}`,
como `tree-grid`. Fundirlos habría hecho imposible tematizar la sangría sin
mover el padding.
3. **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 llama `row` a sus privados. →
`row-*`, coherente con `tree-grid` y con la lección de `table` («el valor es
la altura de la FILA, no del root»). Y fuera el prefijo `root-` del chasis:
el wrapper ES el componente (mismo criterio que `tree-grid`).
4. **`row-padding-block` ⚠ es POR TALLA**, no dos valores en pugna: xs vale
`0` y las otras cuatro `--space-1`. Cinco coordenadas.
5. **`branch-indicator-width` + `-height` son UN knob** (`1em` los dos) →
`branch-indicator-size`. Mismo caso que el checkbox de `grid-list`.
6. **Los shorthand se parten**: `border` de surface/outline/ghost → un
`border-width` + un `border` (color); `padding` de surface/outline →
`padding`. Los `transparent` de ghost/outline y el `padding: 0` de ghost son
IDENTIDAD de variante y se quedan literales, igual que el `100%` de
`[data-block]`.
7. **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 `table` y `tree-grid`, verbatim, no se
«corrige» al 1:1. La altura de fila SÍ es 1:1 con el bundle. Los resueltos
llevan `parts: ['root']`: `data-size` se estampa en `[data-tree-view-root]`,
que es wrapper de eidos y no parte del morfo (precedente `tree-grid`).
8. **`hover-row-bg` SÍ se acuña — al revés que en `grid-list`, y por
medición.** La regla cubre dos nodos con arquetipo distinto:
`branch-control` **no lleva archetype**, así que ahí el plano de la receta
es la ÚNICA pintura (velo ausente: `background-image: none` medido), y el
token es la única superficie de tema del hover. En `[data-tree-view-item]`
(que sí es `item`) 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
caso `grid-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.
<!-- veredicto:end -->

Powered by TurnKey Linux.