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

8.1 KiB

spinner — 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-25 · Alcance: 80% — 16 de 20 knobs por token público
  • Knobs de apariencia: 20 — público 16 · privado 0 · global 0 · literal 4 · sistema 0 · excepción 5 · estructural 0 · puente 0 · canal 0 (los cinco últimos, fuera del ratio)
  • Contrato hoy (lib/recipes/base.ts): 18 pública(s) — size-xs, size-sm, size-md, size-lg, size-xl, thickness-xs, thickness-sm, thickness-md, thickness-lg, thickness-xl, size, thickness, gap, duration, track-opacity, bar-radius, label-font-size, label-fg · 2 privada(s) forward — _palette-text, _palette-track
  • Eje size: no · ficheros: spinner.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 (4)

# fichero:línea selector propiedad valor
1 spinner.css:54 [data-spinner][data-variant='ring'] [data-spinner-track] border-radius 50%
2 spinner.css:73 [data-spinner][data-variant='dots'] [data-spinner-dot] border-radius 50%
3 spinner.css:138 0%, 80%, 100% opacity 0.5
4 spinner.css:142 40% opacity 1

1.4 Excepciones firmadas (5) — 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 spinner.css:31 [data-spinner] color var(--_spinner-color)
2 spinner.css:56 [data-spinner][data-variant='ring'] [data-spinner-track] border-top-color var(--_spinner-color)
3 spinner.css:74 [data-spinner][data-variant='dots'] [data-spinner-dot] background var(--_spinner-color)
4 spinner.css:99 [data-spinner][data-variant='bars'] [data-spinner-bar] background var(--_spinner-color)
5 spinner.css:165 [data-spinner][data-variant='ring'] [data-spinner-track] border-top-color var(--_spinner-track)

2. Sistema transversal (0) — informativo, fuera del ratio

Un tema los alcanza a nivel de sistema, por diseño (recipe-contract §2).

Ninguno.

3. Privados de la receta — ¿de dónde sale su valor?

privado declaraciones valor(es) origen ¿deriva de un público?
--_spinner-color 2 var(--_spinner-palette-text), currentColor literal, private no
--_spinner-track 2 color-mix(in srgb, var(--_spinner-palette-track) 60%, transparent), color-mix(in srgb, currentColor 25%, transparent) literal, private no

Consumidos y no declarados en el CSS (vienen de base.ts o de un estilo inline del wrapper): --_spinner-palette-text, --_spinner-palette-track.

4. Propuesta de corrección

4.1 Tokens a declarar en lib/recipes/base.ts (6)

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 (--spinner-…) scope TSC valor propuesto usos
fg root var(--_spinner-color) 1
ring-track-radius root 50% 1
dots-dot-radius root 50% 1
dots-dot-bg root var(--_spinner-color) 1
bars-bar-bg root var(--_spinner-color) 1
opacity root 0.5 1

4.2 Sin nombre mecánico (3)

  • ⚠ decisión: la propiedad no tiene slot canónico en el vocabulario — 2: border-top-color.
  • ⚠ 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: opacity.

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

Medido 2026-08-21 (sonda ×2 sobre el mismo código = 0 diffs en 377 valores · 7 estados). La §4 propone 71 tokens para 23 knobs, y es el peor caso de inflación que ha dado el generador en todo el eje. Corregido queda en 18 claves.

  1. El spinner tiene UNA coordenada de talla, no veinte. Todo su tamaño sale de --_spinner-size (0.75/1/1.25/1.75/2.5rem) y todo su trazo de --_spinner-thickness. La §4.1 multiplica esa única coordenada por variante × parte × dimensión × talla y produce ring-track-width-xs, dots-track-gap-xs, dots-dot-width-xs, bars-track-gap-xs… todos con el mismo valor 0.75rem, porque todos SON --_spinner-size en xs. Un tema tendría que escribir veinte claves para cambiar un número. Las dos coordenadas reales, por talla, son diez claves; con sus dos resueltos, doce.
  2. Las proporciones son CONSTRUCCIÓN, no knobs. calc(size * 0.2) (hueco entre puntos), * 0.3 (diámetro del punto), * 0.12 (hueco entre barras) y * 0.18 (ancho de barra) son la FORMA de cada variante: lo que define que un punto sea un punto. Se quedan en la receta, igual que los cinco gradientes de las guías de tree-grid o el damero de gradient-builder. El knob es size; la proporción es el dibujo.
  3. fg / dots-dot-bg / bars-bar-bg ⚠ NO son tres knobs ni tienen dos valores en pugna: son una sola variable (--_spinner-color) leída en tres sitios, con el conmutador data-color='inherit' que la cambia de forward de paleta a currentColor. Es el mismo patrón que --_textarea-border-focus: una variable, dos fuentes. Se queda privada — igual que --_spinner-track, que además envuelve su fuente en un color-mix distinto por rama (60 % en el modo normal, 25 % en inherit).
  4. La escala NO casa con el bundle de iconos, medido: el spinner va 12/16/20/28/40 px y --icon-size-* va 14/16/18/20/32 — sólo coincide en sm. Es una escala propia, más generosa de md en adelante, y se escribe verbatim con la desviación anotada (mismo criterio que el padding de textarea). Forzarla al bundle habría movido el default en cuatro tallas de cinco.
  5. duration entra al contrato. Hoy es 0.9s a pelo, y el registro ya tiene abierta la incoherencia de que feed ganó tokens de duración para su spinner mientras media-player conserva los suyos crudos (§13). Aquí se hace bien de entrada; el precedente de nombre es feed.sentinel-spinner-duration.
  6. track-opacity sólo pinta bajo prefers-reduced-motion — su única declaración vive en ese bloque de media, así que el guard lo verá mudo salvo emulando el contexto (precedente exacto: feed.sentinel-spinner-reduced-duration).
  7. Fuera del contrato: los dos border-radius: 50% (identidad de forma — un punto redondo es redondo) y los opacity: 0.5 / 1 de los @keyframes, que son fotogramas de la animación, no knobs.

Powered by TurnKey Linux.