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/collapsible.md

104 lines
5.2 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.

# collapsible — 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-24 · **Alcance**: **100%** — 10 de 10 knobs por token público
- **Knobs de apariencia**: 12 — público 10 · privado 0 · global 0 · literal 0 · sistema 2 · excepción 0 _(los dos últimos, fuera del ratio)_
- **Contrato hoy** (`lib/recipes/base.ts`): 12 pública(s) — `trigger-font-family`, `trigger-font-size`, `trigger-font-weight`, `trigger-fg`, `hover-trigger-fg`, `trigger-radius`, `trigger-padding`, `trigger-gap`, `content-padding`, `transition-duration`, `transition-ease`, `disabled-opacity`
- **Eje `size`**: no · **ficheros**: `collapsible.css`
## 1. Knobs fuera de alcance
### 1.1 Directo a primitivo global (0)
_Ninguno._
### 1.2 A través de un privado (0)
_Ninguno._
### 1.3 Literales (0)
_Ninguno._
### 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 | `collapsible.css:33` | `[data-collapsible-trigger]:hover:not([data-disabled])` | `background-image` | `linear-gradient(var(--state-hover), var(--state-hover))` |
| 2 | `collapsible.css:38` | `[data-collapsible-trigger]: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._
## 4. Propuesta de corrección
_Nada que proponer: no hay knobs fuera de alcance._
### 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 -->
**Ejecutado 2026-08-24 · 90 % → 100 %** (12 knobs · 10 públicos · 2 sistema
fuera del ratio). Contrato **11 → 12** claves. Diff de computed **VACÍO** (736
valores, 8 estados, 3 nodos: las tres partes del morfo, cerrada y abierta).
Centinela **10/12**, 2 adjudicadas.
**Lo que entró — una clave, la COSTURA.** `trigger-gap` es el único knob que la
receta leía a pelo (`var(--space-2)`): el valor es del sistema y el knob no era
de nadie, así que un tema no podía apretar esta cabecera sin mover el paso de
espaciado en toda la app (PLAN §2-A). El nombre lo decide el catálogo, no la
propuesta: `trigger-gap` ya existe **ocho veces** en `base.ts`, cinco de ellas
con exactamente `var(--space-2)`.
**Lo que NO se acuña, y por qué.** Los dos knobs restantes son **sistema
transversal**, no deuda: el velo de hover es
`linear-gradient(var(--state-hover), var(--state-hover))` —la capa de
`archetypes.css`, nunca una invención por componente— y el anillo de foco es
`--focus-ring-*`. Y **no hay clave de motion que acuñar**: la firma de
apertura/cierre es el par de eventos `emerge-expand` / `emerge-collapse` que
materializa `EidosConfig.motion.signatures`; la receta no declara `@keyframes`
(recipe-contract §2, R-4.5), así que el componente que «anima su apertura» no
tiene ni un knob de animación propio.
**Las dos silenciosas del guard, medidas.** `transition-duration` y
`transition-ease` **SON** la transición que el centinela congela para poder leer
todo lo demás — la clase que `color-picker` documentó el 2026-08-23. Medidas sin
congelar sobre el encabezado real: `0.18s, 0.18s → 4.321s, 4.321s` y
`cubic-bezier(0.4, 0, 0.2, 1) ×2 → steps(3) ×2` (dos entradas porque el trigger
transiciona `background` y `color`). Al ledger con esa razón.
**Y una que NO hizo falta adjudicar.** `disabled-opacity` leía muerta porque el
escenario no lleva el estado. Encender el interruptor `disabled` para toda la
corrida se habría llevado por delante el tinte de hover (`pointer-events: none`
en el provider — la trampa de «montar más mide menos»), así que el estado se
mide como **superficie extra** por la URL de la demo (`?perm.disabled=true`,
precedente `radio-group`): 8/11 → 10/12 con la clave de hover viva en la
primera URL.
**Veredicto: CERRADO al 100 %.** No queda knob fuera del alcance.
<!-- veredicto:end -->

Powered by TurnKey Linux.