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

12 KiB

editable — 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-23 · Alcance: 82% — 31 de 38 knobs por token público
  • Knobs de apariencia: 42 — público 31 · privado 7 · global 0 · literal 0 · sistema 4 · excepción 2 (los dos últimos, fuera del ratio)
  • Contrato hoy (lib/recipes/base.ts): 56 pública(s) — gap-xs, gap-sm, gap-md, gap-lg, gap-xl, control-height-xs, control-height-sm, control-height-md, control-height-lg, control-height-xl, control-padding-inline-xs, control-padding-inline-sm, control-padding-inline-md, control-padding-inline-lg, control-padding-inline-xl, font-family, font-size-xs, font-size-sm, font-size-md, font-size-lg, font-size-xl, line-height, fg, area-min-inline-size, control-radius, control-border-width, hover-control-border, control-bg, control-shadow, placeholder-fg, trigger-gap, trigger-padding-inline, trigger-radius, trigger-border-width, trigger-border, hover-trigger-border, trigger-bg, trigger-fg, hover-trigger-fg, submit-fg, transition-duration, transition-ease, disabled-opacity, disabled-fg, primary-solid, secondary-solid, neutral-solid, affirm-solid, risk-solid, threat-solid, primary-border, secondary-border, neutral-border, affirm-border, risk-border, threat-border · 3 privada(s) forward — _palette-solid, _palette-border, _palette-solid-hover
  • Eje size: sí · ficheros: editable.css

1. Knobs fuera de alcance

1.1 Directo a primitivo global (0)

Ninguno.

1.2 A través de un privado (7)

# fichero:línea selector propiedad valor
1 editable.css:96 [data-editable-input] border-color var(--_editable-palette-border)
2 editable.css:129 [data-editable-input]:hover:not([data-disabled]):not([data-readonly]) border-color var(--_editable-palette-border)
3 editable.css:134 [data-editable-preview]:focus-visible, [data-editable-input]:focus-visible border-color var(--_editable-palette-border)
4 editable.css:185 [data-editable-submit-trigger] border-color var(--_editable-palette-border)
5 editable.css:186 [data-editable-submit-trigger] background var(--_editable-palette-solid)
6 editable.css:198 [data-editable-submit-trigger]:hover:not(:disabled) background var(--_editable-palette-solid-hover)
7 editable.css:199 [data-editable-submit-trigger]:hover:not(:disabled) border-color var(--_editable-palette-solid-hover)

1.3 Literales (0)

Ninguno.

1.4 Excepciones firmadas (2) — 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 editable.css:89 [data-editable-preview] inline-size fit-content
2 editable.css:95 [data-editable-input] inline-size 100%

2. Sistema transversal (4) — 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 editable.css:99 [data-editable-input] outline var(--focus-ring-width) solid var(--focus-ring-color)
2 editable.css:136 [data-editable-preview]:focus-visible, [data-editable-input]:focus-visible outline var(--focus-ring-width) solid var(--focus-ring-color)
3 editable.css:193 [data-editable-edit-trigger]:hover:not(:disabled), [data-editable-cancel-trigger]:hover:not(:disabled) background-image linear-gradient(var(--state-hover), var(--state-hover))
4 editable.css:205 [data-editable-edit-trigger]:focus-visible, [data-editable-submit-trigger]:focus-visible, [data-editable-cancel-trigger]:focus-visible outline var(--focus-ring-width) solid var(--focus-ring-color)

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

privado declaraciones valor(es) origen ¿deriva de un público?
--_editable-gap 5 var(--editable-gap-md), var(--editable-gap-xs), var(--editable-gap-sm), var(--editable-gap-lg), var(--editable-gap-xl) public sí
--_editable-control-height 5 var(--editable-control-height-md), var(--editable-control-height-xs), var(--editable-control-height-sm), var(--editable-control-height-lg), var(--editable-control-height-xl) public sí
--_editable-control-padding-inline 5 var(--editable-control-padding-inline-md), var(--editable-control-padding-inline-xs), var(--editable-control-padding-inline-sm), var(--editable-control-padding-inline-lg), var(--editable-control-padding-inline-xl) public sí
--_editable-font-size 5 var(--editable-font-size-md), var(--editable-font-size-xs), var(--editable-font-size-sm), var(--editable-font-size-lg), var(--editable-font-size-xl) public sí

Consumidos y no declarados en el CSS (vienen de base.ts o de un estilo inline del wrapper): --_editable-palette-border, --_editable-palette-solid, --_editable-palette-solid-hover.

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 (--editable-…) scope TSC valor propuesto usos
preview-width root fit-content 1

4.2 Sin nombre mecánico (8)

  • ⚠ 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.
  • ⚠ 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 — 7: border-color, background.

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 % → 82 %, contrato 56 claves, centinela 42/56 (14 adjudicadas). Diff de computed 0 en las dos caras del componente —modo PREVIEW (1.696 valores) y modo EDICIÓN (2.528)— y la captura 2× del reposo idéntica al byte.

El componente tiene DOS superficies y sólo una está en pantalla. Preview e input comparten celda de rejilla y se excluyen (display: none), igual que los triggers: Edit en reposo, Save/Cancel editando. Cualquier medida de una sola pasada deja fuera la mitad de la receta, así que todo aquí se midió dos veces.

Y la apertura es FRÁGIL en la dirección contraria a la habitual: salir del modo edición es lo que hace un blur —da igual lo que diga submitMode, esa opción sólo decide si el valor se compromete—, y el guard hace blur() justo después de abrir. Abriendo con clic en el trigger, la superficie ya estaba cerrada cuando se medía: submit-fg leía muerto y mueve perfectamente cuando está abierta de verdad (rgb(255,255,255) → rgb(1,2,3)). Se resuelve poniendo la demo en activationMode=focus y abriendo por foco, que es la apertura que el guard no deshace. Regla: antes de creer un «no effect», comprueba que la superficie seguía abierta — la misma de navigation-menu, con el gesto invertido.

Lo que se acuñó (1):

  • disabled-fg — la tinta apagada de TODO el componente (preview, input y los tres triggers comparten UNA regla), así que el nombre desnudo del catálogo es el que toca: label y select ya lo llevan con este mismo valor. Era el único knob que iba a un primitivo a pelo, y encima con un respaldo escrito a mano —var(--color-content-disabled, var(--color-content-muted))— que estaba muerto: el token sí está declarado en :root, así que el respaldo no podía pintar nunca. Retirado con él.

Lo que se retiró (1 clave huérfana):

  • control-border — ninguna regla lo consumía. El borde en reposo del control es transparent por diseño y el del input es el acento (--_editable-palette-border), así que esa clave pública prometía un knob que no existe. Es la deuda INVERSA del eje. Diff 0, y el centinela lo confirma: antes leía muerto.

Dos literales de identidad firmados: el fit-content del preview (es tan ancho como el texto que enseña — la ficha proponía acuñarlo como preview-width, y sería acuñar la definición de la parte) y el 100 % del input (llena la celda de rejilla que comparte con el preview).

Lo que se queda fuera, y por qué (el techo honesto es 82 %): los siete knobs que van por privado son el puente de paleta THM-2 (--_editable-palette-{solid,border,solid-hover}) que la capa compartida alimenta por instancia desde [data-color]; un público encima dejaría que un tema lo fijara y matara el color= de cada instancia (§3.pre del handoff). Los otros cuatro son sistema transversal —anillo de foco y velo de hover— y ya están fuera del ratio.

Las catorce adjudicaciones, en dos razones: el par transition-* ES la transición que el guard congela (medido sin congelar: 0.12s → 4.321s y cubic-bezier(0.4, 0, 0.2, 1) → steps(3)), y las doce claves de tono son la cascada de paleta, adjudicadas por PATRÓN con el mecanismo a la vista: el nodo lleva --palette-solid de la capa por instancia, el bloque genérico [data-editable][data-color] —emitido EL ÚLTIMO, misma especificidad— lo lee, y el respaldo que nombra la clave del componente no llega nunca; quítale data-color a la misma instancia y --editable-primary-solid vuelve a pintar. soma estampa data-color siempre, así que no se escapa ninguna.

⚠ risk-border no cae en ese patrón, y comprobarlo importó: además del camino de paleta, esa clave la leen DIRECTAMENTE las tres reglas de inválido, así que su silencio tiene una segunda causa —la demo es válida— y su adjudicación es propia: forzando data-invalid sobre el root real alcanza en el input Y en el control (oklch(0.8059 0.1123 59.96) → rgb(1, 2, 3)). Una excepción por patrón que engulle una clave con vida propia es una adjudicación falsa.

Defecto real anotado, NO arreglado: ese mismo hecho es el defecto. El estado inválido pinta con la clave de TONO, así que un tema que quiera otro tinte de error tiene que mover el tono risk, que también viste las instancias con color="risk" — dos knobs distintos con una sola llave. El arreglo es una clave de estado por parte (invalid-input-border / invalid-control-border, la forma que switch acuñó el mismo día), y es contrato: se lista.

Powered by TurnKey Linux.