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/search-field.md

138 lines
8.3 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.

# search-field — 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**: **100%** — 10 de 10 knobs por token público
- **Knobs de apariencia**: 11 — público 10 · privado 0 · global 0 · literal 0 · sistema 1 · excepción 4 · estructural 0 · puente 0 · canal 0 _(los cinco últimos, fuera del ratio)_
- **Contrato hoy** (`lib/recipes/base.ts`): 17 pública(s) — `clear-hidden-opacity`, `icon-size-xs`, `icon-size-sm`, `icon-size-md`, `icon-size-lg`, `icon-size-xl`, `icon-fg`, `icon-margin-inline-end`, `loading-indicator-size-xs`, `loading-indicator-size-sm`, `loading-indicator-size-md`, `loading-indicator-size-lg`, `loading-indicator-size-xl`, `loading-indicator-fg`, `loading-indicator-track`, `loading-indicator-thickness`, `loading-indicator-duration`
- **Eje `size`**: sí · **ficheros**: `search-field.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 (4) — 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.
| # | fichero:línea | selector | propiedad | valor |
| ---: | --- | --- | --- | --- |
| 1 | `search-field.css:68` | `[data-search-field-icon]` | `line-height` | `1` |
| 2 | `search-field.css:86` | `[data-search-field-loading-indicator]::before` | `inline-size` | `100%` |
| 3 | `search-field.css:87` | `[data-search-field-loading-indicator]::before` | `block-size` | `100%` |
| 4 | `search-field.css:88` | `[data-search-field-loading-indicator]::before` | `border-radius` | `50%` |
## 2. Sistema transversal (1) — 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 | `search-field.css:105` | `[data-search-field-loading-indicator]::before` | `opacity` | `var(--opacity-muted)` |
## 3. Privados de la receta — ¿de dónde sale su valor?
| privado | declaraciones | valor(es) | origen | ¿deriva de un público? |
| --- | ---: | --- | --- | :-: |
| `--_search-field-icon-size` | 5 | `var(--search-field-icon-size-md)`, `var(--search-field-icon-size-xs)`, `var(--search-field-icon-size-sm)`, `var(--search-field-icon-size-lg)`, `var(--search-field-icon-size-xl)` | public | **sí** |
| `--_search-field-loading-size` | 5 | `var(--search-field-loading-indicator-size-md)`, `var(--search-field-loading-indicator-size-xs)`, `var(--search-field-loading-indicator-size-sm)`, `var(--search-field-loading-indicator-size-lg)`, `var(--search-field-loading-indicator-size-xl)` | public | **sí** |
## 4. Propuesta de corrección
- **Tiene eje `size`**: los tokens dimensionales van por talla (`{part}-{eje}-{k}`) apuntando al bundle `--size-{k}-*`, nunca al primitivo crudo (theming §5; el guard `recipe-css-contract` prohíbe el primitivo).
### 4.1 Tokens a declarar en `lib/recipes/base.ts` (1)
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 (`--search-field-…`) | scope TSC | valor propuesto | usos |
| --- | --- | --- | ---: |
| `loading-indicator-radius` | `root` | `50%` | 1 |
### 4.2 Sin nombre mecánico (3)
- **⚠ decisión: `1` 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: `line-height`.
- **⚠ 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** — 2: `inline-size`, `block-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 -->
**Ejecutado 2026-08-23 — 71 % → 100 %, y CERO claves nuevas.** Diff de computed 0
sobre 1.216 valores en 8 estados (5 nodos); R-5.4 de **7/17 a 17/17 sin una sola
adjudicación**, dos corridas del mismo código de acuerdo; capturas 2×
antes/después **idénticas byte a byte** (`a7a83949…`).
**Su deuda eran CUATRO literales que son identidad**, y ahora van firmados con
`/* literal: … */` (válvula de recipe-contract §3): el `line-height: 1` del icono
—un glifo solo no tiene interlineado, la misma anotación que su hermana
`field.css`—, el `100%` doble del `::before` —el anillo ES la caja del indicador,
que ya mide por `--_search-field-loading-size`— y el `border-radius: 50%`. Este
último la §4 pedía acuñarlo como `loading-indicator-radius`: **sería un knob que
sólo puede romper el componente**. El arco es un BORDE que gira; con cualquier
otro valor la ruleta deja de leerse como una. Es la clase 4 de F2-B, «el 50 % de
un círculo», al pie de la letra.
**Diez de sus diecisiete tokens no se habían medido nunca, y ninguno miente.**
El centinela leía 7/17 porque la demo no monta dos estados: el indicador de carga
sólo existe con `loading` (ocho tokens) y la X sólo se desvanece con el campo
VACÍO, y el escenario arranca con valor (`clear-hidden-opacity`). Los dos
interruptores viven ya en el guard (`prepareWith`), y el orden importa: el clic
en la X tiene que ir PRIMERO, porque la propia regla que enciende le quita
después el `pointer-events` al botón que la disparó. La sonda necesita el
interruptor de `loading` por lo mismo: 4 → **5 nodos**, y sin perder ninguno.
**Los dos privados NO son deuda**: `--_search-field-icon-size` y
`--_search-field-loading-size` son el conmutador por talla y sus cinco fuentes
son, cada una, una clave pública. Se dejan como están: 58 de las 162 recetas
resuelven así su eje `size` —incluidas las cerradas al 100 % este mismo mes
(`empty-state`, `banner`)—, y convertirlas al ámbito `size:` del TSC cambiaría la
especificidad de la emisión sin ganar un punto de alcance.
**Casi nada de su superficie es suyo, y está bien**: el cromo de la fila (borde,
radio, fondo, altura, padding, hueco, tipografía del valor, foco, inválido,
deshabilitado) es de `field.css` por `[data-field-control]`, y el de la X es de
`button.css`. La receta lo dice en su cabecera y no realiasa NADA. Fuera del
ratio queda además `--opacity-muted` del indicador bajo
`prefers-reduced-motion`, que es capa de sistema.
⚠ **Un default medido, ANOTADO, no cambiado**: las dos escalas del mismo renglón
divergen en los dos últimos peldaños. Medido en Chrome con transiciones y
animación congeladas, forzando `data-size` sobre el nodo real —icono →
indicador—: xs 14→14, sm 16→16, md 18→18, **lg 20→18**, **xl 32→20**. El contrato
lo declara así de frente: `loading-indicator-size-lg` apunta a
`--size-md-icon-size` y `-xl` a `--size-lg-icon-size`, mientras la escala del
icono sube peldaño a peldaño. En `xl` la ruleta es DOCE píxeles menor que la lupa
que tiene al lado. No es deuda de alcance —las dos escalas son públicas y las
diez claves alcanzan—, es una decisión de diseño que huele a copia que se quedó a
medias. Cambiarla mueve píxel: D-TH.5 la saca de este eje.
<!-- veredicto:end -->

Powered by TurnKey Linux.