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

15 KiB

avatar — 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-24 · Alcance: 90% — 27 de 30 knobs por token público
  • Knobs de apariencia: 30 — público 27 · privado 3 · global 0 · literal 0 · sistema 0 · excepción 6 (los dos últimos, fuera del ratio)
  • Contrato hoy (lib/recipes/base.ts): 88 pública(s) — size-xs, size-sm, size-md, size-lg, size-xl, size-xxl, font-family, font-size-xs, font-size-sm, font-size-md, font-size-lg, font-size-xl, font-size-xxl, font-weight, radius-full, radius-md, radius-sm, radius-none, border-width, primary-solid-bg, primary-solid-fg, primary-soft-bg, primary-soft-fg, primary-outline-border, primary-outline-fg, secondary-solid-bg, secondary-solid-fg, secondary-soft-bg, secondary-soft-fg, secondary-outline-border, secondary-outline-fg, neutral-solid-bg, neutral-solid-fg, neutral-soft-bg, neutral-soft-fg, neutral-outline-border, neutral-outline-fg, affirm-solid-bg, affirm-solid-fg, affirm-soft-bg, affirm-soft-fg, affirm-outline-border, affirm-outline-fg, fulfill-solid-bg, fulfill-solid-fg, fulfill-soft-bg, fulfill-soft-fg, fulfill-outline-border, fulfill-outline-fg, risk-solid-bg, risk-solid-fg, risk-soft-bg, risk-soft-fg, risk-outline-border, risk-outline-fg, threat-solid-bg, threat-solid-fg, threat-soft-bg, threat-soft-fg, threat-outline-border, threat-outline-fg, loss-solid-bg, loss-solid-fg, loss-soft-bg, loss-soft-fg, loss-outline-border, loss-outline-fg, ring-width-sm, ring-width-md, ring-width-lg, ring-color-custom, badge-border-width, badge-color-custom, badge-color-custom-contrast, group-gap-xs, group-gap-sm, group-gap-md, group-gap-lg, group-overlap-xs, group-overlap-sm, group-overlap-md, group-overlap-lg, group-overlap-xl, group-overlap-xxl, group-carve-width, group-carve-color, group-reverse-z-max, overflow-font-weight · 11 privada(s) forward — _palette-solid, _palette-surface, _palette-contrast, _palette-text, _palette-border, _bg, _fg, _border, _badge-bg, _badge-fg, _badge-border
  • Eje size: sí · ficheros: avatar.css

1. Knobs fuera de alcance

1.1 Directo a primitivo global (0)

Ninguno.

1.2 A través de un privado (3)

# fichero:línea selector propiedad valor
1 avatar.css:38 [data-avatar] background var(--_avatar-bg)
2 avatar.css:39 [data-avatar] color var(--_avatar-fg)
3 avatar.css:224 [data-avatar-badge] background var(--_avatar-badge-bg)

1.3 Literales (0)

Ninguno.

1.4 Excepciones firmadas (6) — 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 avatar.css:98 [data-avatar-image] inline-size 100%
2 avatar.css:99 [data-avatar-image] block-size 100%
3 avatar.css:117 [data-avatar-fallback] inline-size 100%
4 avatar.css:118 [data-avatar-fallback] block-size 100%
5 avatar.css:123 [data-avatar-fallback] line-height 1
6 avatar.css:231 [data-avatar-badge] line-height 1

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?
--_avatar-size 7 var(--avatar-size-md), var(--avatar-size-xs), var(--avatar-size-sm), var(--avatar-size-lg), var(--avatar-size-xl), var(--avatar-size-xxl) public sí
--_avatar-font-size 7 var(--avatar-font-size-md), var(--avatar-font-size-xs), var(--avatar-font-size-sm), var(--avatar-font-size-lg), var(--avatar-font-size-xl), var(--avatar-font-size-xxl) public sí
--_avatar-radius 5 var(--avatar-radius-full), var(--avatar-radius-md), var(--avatar-radius-sm), var(--avatar-radius-none) public sí
--_avatar-ring-color 10 var(--avatar-neutral-solid-bg), var(--avatar-primary-solid-bg), var(--avatar-secondary-solid-bg), var(--avatar-affirm-solid-bg), var(--avatar-fulfill-solid-bg), var(--avatar-risk-solid-bg) …(+3) public sí
--_avatar-ring-width 4 var(--avatar-ring-width-md), var(--avatar-ring-width-sm), var(--avatar-ring-width-lg) public sí
--_avatar-badge-size 1 calc(var(--_avatar-size) * 0.3) private no
--_avatar-badge-dot-size 1 calc(var(--_avatar-size) * 0.26) private no
--_avatar-badge-flip 2 1, -1 literal no
--_avatar-badge-bg 3 var(--avatar-badge-color-custom), color-mix( in srgb, var(--avatar-badge-color-custom) 18%, transparent ), var(--color-surface-default) global, public no
--_avatar-badge-fg 3 var(--avatar-badge-color-custom-contrast), var(--avatar-badge-color-custom) public sí
--_avatar-badge-border 1 var(--avatar-badge-color-custom) public sí
--_avatar-group-overlap 7 var(--avatar-group-overlap-md), var(--avatar-group-overlap-xs), var(--avatar-group-overlap-sm), var(--avatar-group-overlap-lg), var(--avatar-group-overlap-xl), var(--avatar-group-overlap-xxl) public sí

Consumidos y no declarados en el CSS (vienen de base.ts o de un estilo inline del wrapper): --_avatar-bg, --_avatar-border, --_avatar-fg.

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 (--avatar-…) scope TSC valor propuesto usos
badge-bg root ⚠ var(--avatar-badge-color-custom) / color-mix( in srgb, var(--avatar-badge-color-custom) 18%, transparent ) / var(--color-surface-default) 3

4.2 Sin nombre mecánico (8)

  • ⚠ decisión: el privado que alimenta este knob no se declara en el CSS (viene de base.ts o de un estilo inline) — hay que resolverlo antes de nombrarlo — 2: background, color.
  • ⚠ 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 — 4: inline-size, block-size.
  • ⚠ 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 — 2: line-height.

4.3 Avisos sobre los tokens propuestos (1)

  • el privado --_avatar-badge-bg debe pasar a leer este público (o desaparecer) — --avatar-badge-bg

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

Ejecutado 2026-08-23 — 75 % → 90 %, contrato 88 claves, centinela 83/88 (5 adjudicadas). Diff de computed 0 en tres bases (demo de avatar con insignia + anillo: 576 valores · la misma en modo fallback: 384 · demo de AvatarGroup: 3.072) y las dos capturas 2× idénticas al byte.

Lo primero, porque contaminaba todo lo demás: su contrato existía y ningún instrumento lo veía. La entrada avatar de base.ts es la ÚNICA construida por una IIFE (un helper local genera sus 24 ámbitos compuestos), así que su mapa vive un tabulador más adentro, en el return {. El censo la leía como «sin entrada en base.ts» —84 claves invisibles— y el centinela moría con no recipe block for avatar: el componente no se podía medir. Los dos lectores leen ya la IIFE (dedentan el return). Sin eso, el gate de este componente no significaba nada.

Lo que se acuñó (6) y por qué:

  • group-overlap-{xs..xxl} — la escala de solape de AvatarGroup. Había UNA clave, --avatar-group-overlap, y la receta la re-declaraba en seis bloques [data-size]: sentada en el elemento, ganaba siempre al :root donde escribe un tema. Medido: desde el asiento del tema, 37px no movía el margen ni un píxel; escrita sobre el nodo, sí. Es un falso positivo del centinela (escribe el token también sobre cada nodo del componente, y para una propiedad personalizada que la receta re-declara EN EL ELEMENTO ese inline sí gana), y queda anotado como límite del instrumento. Ahora el paso viaja por --_avatar-group-overlap y los seis alcanzan desde :root (−8,4 · −11,2 · −14 · −16,8 · −22,4 · −33,6 px → 37 px, uno a uno).

Lo que se retiró (2 declaraciones muertas, diff 0 las dos):

  • group-max — el envoltorio escribía --avatar-group-max INLINE y la receta declaraba su default 99; no lo leía nadie. El tope se aplica con data-has-max + :nth-child(n + M) porque una variable no entra en :nth-child() — lo dice el propio comentario del CSS. Retirada de los dos sitios: el +3 del grupo sigue exactamente donde estaba.
  • el respaldo , white de --_avatar-badge-fg: el contrato ya declara --avatar-badge-color-custom-contrast: white (desde 2026-08-25, --avatar-badge-fg-custom-contrast), así que el respaldo era inalcanzable y sólo podía envejecer contra su token (la clase del , 1.4 contra --font-line-height-sm). Comprobado en la rama custom: la tinta sigue computando rgb(255, 255, 255).

Nota 2026-08-25: las tablas generadas de §1–§4 de esta ficha siguen nombrando --avatar-badge-color-custom y --avatar-ring-color-custom como públicas. Es fotografía vieja: la firma A-c las retiró del contrato ese día (ver §5). Se corrigen solas en la próxima regeneración del censo; no se regeneró aquí para no mezclar en esta firma un diff que no es suyo.

Seis literales firmados (salen del ratio, clase exception): los cuatro 100 % de Image y Fallback son IDENTIDAD —la parte ES la superficie del avatar, no una talla propia— y los dos line-height: 1 mantienen el glifo centrado por la caja flex; con interlineado se descentra.

Lo que se queda fuera, y por qué (los 3 privados, el techo real es 90 %): --_avatar-bg, --_avatar-fg y --_avatar-badge-bg son un CONMUTADOR — cambian de fuente con la variante (solid · soft · outline) y su valor sale del forward de paleta THM-2 que la capa de color alimenta por instancia desde [data-color]. Un público encima dejaría que un tema los fijara y matara el color= de cada avatar (la razón de §3.pre del handoff). Aplanarlos obligaría además a duplicar cada regla por tono: 24 combinaciones.

Las cinco adjudicaciones del centinela (todas medidas a mano sobre el nodo REAL, con transiciones congeladas): size-xxl y font-size-xxl viven en el paso xxl, que el barrido de tallas del guard no alcanza (para en xl — el mismo límite que metrics ya registró); radius-none y ring-width-sm son «sólo el paso en vigor pinta»; group-overlap-xxl junta las dos cosas.

Una SEXTA adjudicación desde 2026-08-25, y de otra clase: no es el escenario sino el INSTRUMENTO. badge-fg-custom-contrast alcanza perfectamente (desde :root, white → rgb(4,5,6)), pero sentinelFor() elige el valor de sonda por el NOMBRE de la clave y su prueba de tinta es fg$ — la cadena lleva -bg- pero no -fg-, así que un fg MEDIAL cae al default 1234px, inválido para color:. Reproducido bajo las condiciones del propio guard: con 1234px no mueve en ningún combo, con rgb(1, 2, 3) mueve en solid. Leía VIVA hasta el renombre, cuando el nombre dejó de casar color. Son cinco claves así en el catálogo y las cinco las fabrica D-TH.6 (next-features §13).

Defectos reales que NO se arreglan aquí:

  1. R-5.3, cuatro claves fuera de la gramática, PREEXISTENTES: ring-color-custom, badge-color-custom, badge-color-custom-contrast (y la cuarta que el audit trunca). La tinta es fg, no color. — FIRMADA Y EJECUTADA 2026-08-25 (opción A-c; la cuarta que el audit truncaba es group-carve-color). Eran las únicas 4 desviaciones de 4.558 claves públicas del catálogo, y no eran la misma cosa: una se renombró (badge-color-custom-contrast → badge-fg-custom-contrast, la única que es tinta de verdad y la única de las tres *-custom* que alcanza desde :root — medido white → rgb(4,5,6)); dos se retiraron del contrato (ring-color-custom y badge-color-custom son canal de valor: la puerta y el inline salen de la misma expresión, así que ningún tema puede ganarles; pasan a privadas --_avatar-{ring,badge}-color-custom leídas con var(…, currentColor), la forma que usan las 5 privadas de envoltorio del parque y la adjudicación que tabs hizo con su indicador); y una quedó EXENTA (group-carve-color alimenta box-shadow — la geometría del carve, no tinta; group-carve-fg sería gramática correcta y semántica peor). Contrato 88 → 86 («Tokens 86» en vivo), censo --names 4 → 0 en todo el catálogo, sonda 0 diffs sobre 576 valores, 0 píxeles. Detalle en PLAN-theming §8.
  2. El barrido de tallas del centinela no llega a xxl; añadirlo dejaría STALE las seis excepciones que metrics escribió por lo mismo, así que se respeta el precedente y se adjudica.

Powered by TurnKey Linux.