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

9.9 KiB

menubar — 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: 88% — 23 de 26 knobs por token público
  • Knobs de apariencia: 27 — público 23 · privado 0 · global 3 · literal 0 · sistema 1 · excepción 0 · estructural 0 · puente 0 · canal 0 (los cinco últimos, fuera del ratio)
  • Contrato hoy (lib/recipes/base.ts): 35 pública(s) — bg, border-fg, border-width, radius, gap-sm, gap-md, gap-lg, padding-sm, padding-md, padding-lg, height-sm, height-md, height-lg, trigger-fg, trigger-font-family, trigger-font-weight, trigger-line-height, trigger-font-size-sm, trigger-font-size-md, trigger-font-size-lg, trigger-padding-inline-sm, trigger-padding-inline-md, trigger-padding-inline-lg, open-trigger-bg, open-trigger-fg, disabled-trigger-fg, panel-z, panel-min-width, panel-max-height, panel-padding, panel-radius, panel-fg, panel-font-size-sm, panel-font-size-md, panel-font-size-lg
  • Eje size: sí · ficheros: menubar.css

1. Knobs fuera de alcance

1.1 Directo a primitivo global (3)

# fichero:línea selector propiedad valor
1 menubar.css:91 [data-menubar-trigger]:hover:not([data-disabled]), [data-menubar-trigger][data-highlighted]:not([data-disabled]) background var(--color-surface-overlay)
2 menubar.css:188 [data-menubar-panel] font-family var(--style-label-font-family)
3 menubar.css:190 [data-menubar-panel] line-height var(--leading-ui)

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 (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 menubar.css:102 [data-menubar-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?
--_menubar-height 3 var(--menubar-height-md), var(--menubar-height-sm), var(--menubar-height-lg) public sí
--_menubar-padding 3 var(--menubar-padding-md), var(--menubar-padding-sm), var(--menubar-padding-lg) public sí
--_menubar-gap 3 var(--menubar-gap-md), var(--menubar-gap-sm), var(--menubar-gap-lg) public sí
--_menubar-radius 1 var(--menubar-radius) public sí
--_menubar-trigger-padding-inline 3 var(--menubar-trigger-padding-inline-md), var(--menubar-trigger-padding-inline-sm), var(--menubar-trigger-padding-inline-lg) public sí
--_menubar-font-size 3 var(--menubar-trigger-font-size-md), var(--menubar-trigger-font-size-sm), var(--menubar-trigger-font-size-lg) public sí

4. Propuesta de corrección

  • Consume la capa compartida list-surface. Un eje que la capa posee se consume como var(--_x, var(--x)); el consumidor no acuña --menubar-{eje} para él — sería un vocabulario paralelo (README de eidos/components, «Capas compartidas» regla 2).
  • Consume la capa compartida menu-indicator. Un eje que la capa posee se consume como var(--_x, var(--x)); el consumidor no acuña --menubar-{eje} para él — sería un vocabulario paralelo (README de eidos/components, «Capas compartidas» regla 2).
  • 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 (3)

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 (--menubar-…) scope TSC valor propuesto usos
hover-trigger-bg root var(--color-surface-overlay) 1
panel-font-family root var(--style-label-font-family) 1
panel-line-height root var(--leading-ui) 1

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 — 15 % → 88 %, 30 claves nuevas (5 → 35). El 12 % restante son TRES filas que NO se acuñan, y ninguna es deuda de este eje.

Lo acuñado, por parte:

  • La barra: superficie (bg), marco (border-fg + border-width) y radius —uno solo, porque la receta lo desacopla de la talla a propósito (modelo Radix) y el motor de forma deriva el del disparador de él—, más las tres escalas por talla (gap-*, padding-*, height-*).
  • El disparador: tinta, tipografía (familia, peso, interlínea), la escala de font-size y la de padding-inline, el par de la entrada ABIERTA (open-trigger-bg / -fg, que hoy comparten valor con el reposo pero son otro estado) y la tinta deshabilitada.
  • El Panel (la superficie role=dialog, la alternativa al Content): sus cinco claves de siempre más la tinta y la escala de font-size.

Los pasos de talla leen el BUNDLE, no el primitivo: height-{k} → --size-{k}-control-height y font-size-{k} → --size-{k}-font-size (regla de recipe-css-contract; el CSS venía leyendo --control-height-md y --font-size-md crudos). El calc(var(--space-1) * 0.5) del paso sm es var(--space-0-5) exacto: mismo computado, un literal menos.

El hueco del panel deja de repetir el valor del padding: las tres reglas de --floating-gap compensaban el sangrado del disparador dentro de la barra con una COPIA del padding (--space-1, * 0.5, --space-2). Ahora leen --menubar-padding-{k}, que es su fuente — si un tema ensancha el padding, el panel deja de quedar a ras. No pueden leer el privado --_menubar-padding porque esas superficies viajan POR PORTAL, y un privado declarado en la raíz no cruza esa frontera (la misma ley que mató el eje size del color-picker).

Las dos que NO se acuñan, medidas: el plano overlay GANA a la receta. Acuñé panel-font-family y panel-line-height, y el centinela las dio muertas. La causa, medida: [data-depth='overlay'] declara las DOS con la misma especificidad (0,1,0) y más tarde en la cascada, así que gana — mientras panel-fg y panel-font-size-*, del MISMO bloque, sí alcanzan (el plano no las declara). Retiradas del contrato y devueltas a su fuente literal con la razón escrita en el CSS: es la cuarta prueba de §12.9, y la primera que da el MECANISMO — no es que el plano imponga tipografía donde el componente calla, es que gana donde el componente habla. Mientras §12.9 no se firme, un token de tipografía en cualquier superficie overlay MIENTE.

La tercera es el hover, y es del OTRO eje. background: var(--color-surface-overlay) sobre el disparador es una invención por componente Y mata la capa del sistema: medido en hover, background-image computa none con --state-hover vivo. Dos razones, las dos documentadas ya en navigation-menu.css, que retiró esta misma regla: el shorthand resetea background-image, y la regla del arquetipo va en :where() (especificidad CERO), así que cualquier regla del componente la tapa. El eje navigation-menu tiene a menubar en su cola por esto mismo; acuñar aquí un hover-trigger-bg habría fosilizado la invención.

Instrumento — dos cegueras arregladas antes de medir (la barra suelta DOS superficies y sólo una lleva sus knobs): la sonda y el centinela abrían el PRIMER disparador, que suelta un Content role=menu cuyo cromo es de dropdown-menu; el Panel cuelga de la entrada «Format». Con OPEN_TRIGGER en la sonda y openWith en el guard, el panel entra en la medida. Y el guard necesitó openMarker: su comprobación de «ya está abierto» busca [data-{c}-content], que aquí no existe, así que volvía a pulsar el disparador antes de cada token y CERRABA el panel — media corrida contra una superficie cerrada.

Verificación: diff de computed = 0 sobre 1.470 valores en 8 estados · centinela 34/35 (la deshabilitada, adjudicada por escrito) · censo 88 % · --names sin desviadas · component:audit PASS · rtl:check 0 · docs:check 0 · suite eidos con el rojo conocido (skin-media-player, ajeno) · check sin errores propios · captura de barra, tallas sm/lg, menú abierto y panel.

Powered by TurnKey Linux.