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

152 lines
9.6 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.

# dialog — 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-23 · **Alcance**: **89%** — 31 de 35 knobs por token público
- **Knobs de apariencia**: 35 — público 31 · privado 4 · global 0 · literal 0 · sistema 0 · excepción 1 _(los dos últimos, fuera del ratio)_
- **Contrato hoy** (`lib/recipes/base.ts`): 44 pública(s) — `overlay-bg`, `overlay-opacity`, `overlay-blur`, `overlay-z`, `content-z`, `content-fg`, `content-radius`, `content-max-height`, `content-max-height-sheet`, `content-width-sm`, `content-width-md`, `content-width-lg`, `content-width-xl`, `content-width-inset`, `content-full-inset`, `content-full-radius`, `content-position-inset`, `content-padding-sm`, `content-padding-md`, `content-padding-lg`, `content-padding-full`, `stack-gap`, `header-gap`, `footer-gap`, `footer-margin-top`, `title-font-family`, `title-font-size`, `title-font-weight`, `title-line-height`, `title-letter-spacing`, `title-fg`, `description-font-family`, `description-font-size`, `description-line-height`, `description-fg`, `risk-border`, `risk-title-fg`, `threat-border`, `threat-title-fg`, `saved-border`, `failed-border`, `dismissed-border`, `close-size`, `close-inset`
- **Eje `size`**: sí · **ficheros**: `dialog.css`
## 1. Knobs fuera de alcance
### 1.1 Directo a primitivo global (0)
_Ninguno._
### 1.2 A través de un privado (4)
| # | fichero:línea | selector | propiedad | valor |
| ---: | --- | --- | --- | --- |
| 1 | `dialog.css:63` | `[data-dialog-content]` | `min-width` | `var(--_dialog-content-min-width-override, auto)` |
| 2 | `dialog.css:65` | `[data-dialog-content]` | `height` | `var(--_dialog-content-height-override, auto)` |
| 3 | `dialog.css:66` | `[data-dialog-content]` | `min-height` | `var(--_dialog-content-min-height-override, auto)` |
| 4 | `dialog.css:184` | `[data-dialog-content][data-size='full']` | `width` | `var(--_dialog-content-width-override, auto)` |
### 1.3 Literales (0)
_Ninguno._
### 1.4 Excepciones firmadas (1) — 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 | `dialog.css:197` | `[data-dialog-content][data-sheet]` | `width` | `100%` |
## 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? |
| --- | ---: | --- | --- | :-: |
| `--_dialog-size-width` | 5 | `var(--dialog-content-width-md)`, `var(--dialog-content-width-sm)`, `var(--dialog-content-width-lg)`, `var(--dialog-content-width-xl)` | public | **sí** |
| `--_dialog-padding` | 7 | `var(--dialog-content-padding-md)`, `var(--dialog-content-padding-sm)`, `var(--dialog-content-padding-lg)`, `var(--dialog-content-padding-full)` | public | **sí** |
| `--_dialog-width` | 1 | `var(--_dialog-content-width-override, var(--_dialog-size-width))` | private | no |
Consumidos y **no declarados en el CSS** (vienen de `base.ts` o de un estilo inline del wrapper): `--_dialog-content-height-override`, `--_dialog-content-max-height-override`, `--_dialog-content-max-width-override`, `--_dialog-content-min-height-override`, `--_dialog-content-min-width-override`, `--_dialog-content-width-override`.
## 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` (0)
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 (`--dialog-…`) | scope TSC | valor propuesto | usos |
| --- | --- | --- | ---: |
### 4.2 Sin nombre mecánico (5)
- **⚠ decisión: `min-width` es shorthand o eje físico — hay que partirlo en ejes lógicos antes de nombrarlo (recipe-contract §1, R-4.4)** — 1: `min-width`.
- **⚠ decisión: `height` es shorthand o eje físico — hay que partirlo en ejes lógicos antes de nombrarlo (recipe-contract §1, R-4.4)** — 1: `height`.
- **⚠ decisión: `min-height` es shorthand o eje físico — hay que partirlo en ejes lógicos antes de nombrarlo (recipe-contract §1, R-4.4)** — 1: `min-height`.
- **⚠ decisión: `width` es shorthand o eje físico — hay que partirlo en ejes lógicos antes de nombrarlo (recipe-contract §1, R-4.4)** — 2: `width`.
### 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 — 67 % → 89 %.** Siete claves nuevas (37 → 44), un
literal firmado, siete adjudicaciones medidas. Diff de computed **0 sobre 480
valores en 8 estados**.
**Las siete son las dos tintas SEMÁNTICAS que le faltaban.** Cuatro para los
tonos evaluativos (`risk-border`, `risk-title-fg`, `threat-border`,
`threat-title-fg`): dialog no tiene forward de paleta THM-2 y su trato de tono es
deliberadamente estrecho —el borde y la tinta del TÍTULO, nunca la superficie del
cuerpo, para que el texto largo no compita con la señal—, pero iban a
`--color-risk-*` a pelo. Y tres para el tinte de SALIDA (`saved-border`,
`failed-border`, `dismissed-border`): el morfo escribe `data-last-action` antes
de que `data-state` pase a `closed`, así que el borde superior dice CÓMO se cerró
mientras se va. El nombre de la tercera cubre `cancelled` / `dismissed` /
`dismissed-outside`, que comparten valor — todo cierre sin resultado.
`{tono}-border` es el nombre del catálogo (48 claves) y `failed-border` el de
`proof-of-human`.
**El 11 % que queda son los cuatro `--_dialog-content-*-override`**, y no es
deuda: son ESCOTILLAS POR INSTANCIA que el wrapper escribe inline desde las
props `width` / `minWidth` / `maxWidth` / `height` / `minHeight`. Un público
encima lo pisaría el inline y mentiría — la clase de
`--_background-gradient-image` y del triple de `s-text-virtual-list`. El nombre
del privado lo dice: `-override`.
⚠ **No se acuñó tipografía de superficie, por §12.9.** El contenido lleva
`data-depth='modal'` y un plano declara `font-family` / `line-height` con la
misma especificidad y más tarde en la cascada. Las claves de título y descripción
que ya existían son de PARTES internas, no de la superficie del plano, así que no
las toca la firma pendiente.
**Las siete adjudicaciones son estados que la demo no monta**: la hoja inferior,
el tamaño `full`, las ocho celdas no centradas de la rejilla de posición, el
`data-position` del botón de cierre y los tres tintes de salida (que sólo existen
en la ventana en que `data-state='closed'` y `data-last-action` COEXISTEN).
Todas forzadas sobre el nodo real y medidas.
⚠ **Dos de ellas costaron una segunda pasada por el valor del atributo**: la
rejilla de posición usa `top-left` / `top-right` (físicos), no `top-start`, y el
botón de cierre **no lleva `data-position` en esta demo**, aunque todas las
reglas que leen `close-inset` lo exigen. Forzar el atributo correcto las mueve
las dos.
⚠⚠ **CORRECCIÓN del mismo día: `overlay-opacity` es un FALSO POSITIVO del
guard.** Lo dio por vivo, y no lo es: `dialog-overlay.svelte` escribe
`--dialog-overlay-opacity` en el `style` INLINE del velo, y el guard escribe su
centinela en el `style` de cada nodo — así que se pisa a sí mismo y ve un
cambio. Medido como lo haría un TEMA, sólo desde `:root` y con las animaciones
congeladas: el fondo del velo **no se mueve**
(`color(srgb 0.1098 0.098 0.0902 / 0.2518)` antes y después); desde el inline sí.
**La clave está en el contrato y ningún tema la alcanza.** Es la cara opuesta de
`drag-drop.preview-z` y la misma familia que el velo de `drawer` que no pinta.
Registrado en §13 con el arreglo propuesto para el guard; retirar o rescatar la
clave es decisión aparte, porque cambia quién controla la opacidad del velo.
**Verificación**: sonda antes/después **0 diffs** (480 valores · 8 estados · 8
nodos con el diálogo abierto) · R-5.4 **37/44** con las siete adjudicadas, exit 0
· `component:audit` PASS · censo 89 % con las cuatro escotillas explicadas ·
`eidos-lint` 15 morfo-backed / **0 invalid, 0 class-hooks** · capturas 2×.
<!-- veredicto:end -->

Powered by TurnKey Linux.