uix(slider): temable — 97 % → 100 %, y con un solo valor el tick ACTIVO no existe

CERO claves acuñadas. El componente llegaba con `global` a cero, `private` a
cero —sus cuatro privados son la escala por talla, que ya deriva de públicos— y
treinta y nueve claves cubriendo su cromo entero; lo único fuera de alcance era
UN literal. Este commit lo firma, adjudica sus siete silenciosas y escribe los
artefactos que le faltaban.

QUÉ ENTRA

- **El literal se firma como identidad**: `inline-size: 100%` en
  `[data-slider][data-orientation='horizontal']` — un rail ocupa su contenedor.
  El knob de verdad ya existe y es su SUELO: `min-inline-size`. Mismo
  precedente que `separator.css:26`, cerrado el mismo día también sin acuñar.
- **Siete adjudicaciones en el ledger**, todas MEDIDAS sobre los nodos reales,
  con `transition` congelada salvo donde el token ES la transición:
  - `min-block-size` — sólo la lee `[data-orientation='vertical']` y el
    escenario arranca horizontal. Con el chip de orientación: 160px -> 1234px.
  - `active-thumb-scale` / `active-thumb-shadow` — el pickup vive en
    `[data-slider-thumb]:active`, que pide el puntero MANTENIDO, y el pase
    estático del guard lo aparca. Con `mouse.down()` real sobre el thumb real:
    scale 1.15 -> 4.56, y la sombra sigue al centinela.
  - `active-tick-bg` — un tick lleva `data-active` sólo mientras su valor cae
    DENTRO de [min(valores), max(valores)] (soma, `SliderTickProvider.isActive`),
    así que un pulgar único en 40 con ticks en 0/50/100 deja los tres inactivos:
    la marca activa no es un estado del tick, es una RELACIÓN CON EL RANGO. Con
    el chip `multiple` (20–80) el tick 50 se activa y el token alcanza.
  - `disabled-opacity` — el escenario arranca habilitado; con su interruptor,
    0.4 -> 0.123.
  - `transition-duration` / `transition-ease` — SON la transición que el guard
    congela; medidos sin congelar, 0.12s -> 11.5s y steps(4).
- README con su sección «Talla y tema» (39 claves por grupo, con la distinción
  `hit-size-{k}` = agarre vs `track-size-{k}` = pintura) y veredicto §5 de la
  ficha con las cifras.

QUÉ NO SE TOCA

- **Nada se retira ni se renombra**, y no es prudencia: este contrato lo COMPONEN
  otros SIETE componentes que re-tiñen o re-dimensionan estas mismas claves sobre
  su Slider embebido — `media-player`, `skin-media-player`, `waveform` (su
  playhead ES este thumb), `color-picker`, `gradient-builder`,
  `image-adjustments` y `time-range-picker`. `min-block-size`, que el centinela
  leía muerta, es justo la que `media-player` escribe para su volumen vertical.
- `base.ts` y `generated/base.css`: sin cambio de contrato no hay nada que
  regenerar. 39 -> 39 claves.

ARTEFACTOS

- Censo: 97 % (33 knobs · 31 públicos · 1 literal · 1 sistema) -> **100 %**
  (32 · 31 · 0 literal · 1 excepción · 1 sistema). Global 68 %, no baja.
- Sonda antes/después: **0 diffs sobre 1.376 valores computados**, 7 estados,
  7 nodos (raíz · secondary-range · range · thumb · 3 ticks).
- Captura 2× antes y después: idénticas.
- Centinela R-5.4: **32/39**, las 7 restantes adjudicadas -> verde.
- component-audit PASS · eidos-lint 25 morfo-backed / 5 eidos-only / **0
  invalid** · `vitest run src/uix/eidos` 35/36 ficheros (el rojo conocido es
  `skin-media-player`) · rtl:check 0 · docs:check 0.
- `npm run check`: UN error en `web/routes/uix/components/slider/+page.svelte`
  (`Property 'keyboard' does not exist`, línea del `sliderMorfo.parts[2]`),
  **PREEXISTENTE** desde `1857c7854` y ajeno a este commit; ningún otro error en
  ficheros de slider.
- Prettier: los hunks de deriva del fichero son los MISMOS que en HEAD (2 en el
  README, 0 en el CSS); mi bloque no añade ninguno.

NOTA DE CONCURRENCIA: la pestaña `Tokens` de su demo (paso 11 del protocolo) la
escribí yo, pero entró en HEAD por `9fc38b19a` + `c88b2f861` de otra sesión, que
la arrastró con un `git add` derivado y lo declaró. No se re-commitea aquí.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
alpha-0.1-background
dev 2 months ago
parent 3282ef9786
commit 4d3ca2fd81

@ -5,8 +5,8 @@
> Vista de conjunto: [README](./README.md) · método y protocolo:
> [`PLAN-theming.md`](../../process/PLAN-theming.md) §1, §2, §7.
- **Medido**: 2026-08-24 · **Alcance**: **97%** — 31 de 32 knobs por token público
- **Knobs de apariencia**: 33 — público 31 · privado 0 · global 0 · literal 1 · sistema 1 · excepción 0 _(los dos últimos, fuera del ratio)_
- **Medido**: 2026-08-24 · **Alcance**: **100%** — 31 de 31 knobs por token público
- **Knobs de apariencia**: 32 — público 31 · privado 0 · global 0 · literal 0 · sistema 1 · excepción 1 _(los dos últimos, fuera del ratio)_
- **Contrato hoy** (`lib/recipes/base.ts`): 39 pública(s) — `track-size-xs`, `track-size-sm`, `track-size-md`, `track-size-lg`, `track-size-xl`, `thumb-size-xs`, `thumb-size-sm`, `thumb-size-md`, `thumb-size-lg`, `thumb-size-xl`, `hit-size-xs`, `hit-size-sm`, `hit-size-md`, `hit-size-lg`, `hit-size-xl`, `tick-size-xs`, `tick-size-sm`, `tick-size-md`, `tick-size-lg`, `tick-size-xl`, `min-inline-size`, `min-block-size`, `track-radius`, `track-bg`, `range-bg`, `secondary-bg`, `thumb-radius`, `thumb-border-width`, `thumb-border`, `thumb-bg`, `thumb-shadow`, `active-thumb-scale`, `active-thumb-shadow`, `tick-radius`, `tick-bg`, `active-tick-bg`, `transition-duration`, `transition-ease`, `disabled-opacity`
- **Eje `size`**: sí · **ficheros**: `slider.css`
@ -20,20 +20,20 @@ _Ninguno._
_Ninguno._
### 1.3 Literales (1)
### 1.3 Literales (0)
| # | fichero:línea | selector | propiedad | valor |
| ---: | --- | --- | --- | --- |
| 1 | `slider.css:70` | `[data-slider][data-orientation='horizontal']` | `inline-size` | `100%` |
_Ninguno._
### 1.4 Excepciones firmadas (0) — fuera del ratio
### 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.
_Ninguno._
| # | fichero:línea | selector | propiedad | valor |
| ---: | --- | --- | --- | --- |
| 1 | `slider.css:70` | `[data-slider][data-orientation='horizontal']` | `inline-size` | `100%` |
## 2. Sistema transversal (1) — informativo, fuera del ratio
Un tema los alcanza **a nivel de sistema**, por diseño (recipe-contract §2).
@ -82,6 +82,57 @@ no distingue lo que debería — se marca `⚠`.
<!-- veredicto:start -->
_(pendiente — lo escribe el autor; se conserva al regenerar)_
**Medido y CERRADO al 100 % el 2026-08-24** (97 % → 100 %, contrato **39 → 39**
claves —ninguna acuñada—, centinela **32/39** con 7 adjudicadas, diff de computed
**0 sobre 1.376 valores** en 7 estados, 7 nodos).
**No entra una sola clave.** El componente llegaba con `global` a cero,
`private` a cero —sus cuatro privados son la escala resuelta por talla, que ya
deriva de públicos— y treinta y nueve claves cubriendo su cromo entero. Lo único
fuera de alcance era **un literal**: el `inline-size: 100%` del rail horizontal.
Es identidad —un rail ocupa su contenedor— y va firmado; el knob de verdad
existe y se llama `min-inline-size`, que es su SUELO. Precedente literal:
`separator.css:26`, cerrado el mismo día con la misma frase y también sin acuñar
nada.
**Las siete silenciosas del centinela están VIVAS.** Ninguna miente: el
escenario sólo lleva puesta una de sus caras. Medidas una a una sobre los nodos
reales, con `transition` congelada salvo donde el token ES la transición:
- **`min-block-size`** — sólo `[data-slider][data-orientation='vertical']` la
lee. Con el chip de orientación de la demo: `160px → 1234px` en `block-size` y
`min-block-size`.
- **`active-thumb-scale` / `active-thumb-shadow`** — el pickup vive en
`[data-slider-thumb]:active` y pide el puntero MANTENIDO; el pase estático del
guard lo aparca. Con un `mouse.down()` real sobre el thumb real:
`scale 1.15 → 4.56` y la sombra sigue al centinela.
- **`active-tick-bg`** — un tick lleva `data-active` sólo mientras su valor cae
DENTRO de `[min(valores), max(valores)]` (soma, `SliderTickProvider.isActive`),
así que un pulgar único en 40 con ticks en 0/50/100 deja los tres inactivos:
**la marca activa no es un estado del tick, es una relación con el rango**. Con
el chip `multiple` (20–80) el tick 50 se activa y el token alcanza.
- **`disabled-opacity`** — el escenario arranca habilitado; con su propio
interruptor, `opacity 0.4 → 0.123`.
- **`transition-duration` / `transition-ease`** — SON la transición que el guard
congela para poder medir lo demás. Sin congelar: `0.12s → 11.5s` en las cuatro
propiedades transicionadas del thumb, y `steps(4)`.
**`hit-size-{k}` y `track-size-{k}` son dos knobs a propósito**, y conviene que
quede escrito antes de que alguien los funda: el primero es el área de agarre
(la altura del control), el segundo el grosor de la pintura sobre el `::before`
de la raíz. Un rail de 6 px con 32 px de agarre es el objetivo táctil, no un
descuadre.
**Este contrato lo COMPONEN otros siete componentes** —`media-player`,
`skin-media-player`, `waveform` (su playhead ES este thumb), `color-picker`,
`gradient-builder`, `image-adjustments` y `time-range-picker`— que re-tiñen o
re-dimensionan estas mismas claves sobre su Slider embebido. `min-block-size`,
que el centinela leía muerta, es exactamente la que `media-player` escribe para
su volumen vertical. **Ninguna clave de este bloque se retira ni se renombra sin
barrer esos siete.**
**Lo que este componente enseña**: cuando el escenario lleva un solo valor, el
estado «activo» de un indicador de rango **no existe**, y el guard lo lee como
un token que miente.
<!-- veredicto:end -->

@ -21,6 +21,26 @@ const PLANE_SUPERSEDED =
'SUPERSEDED by the depth plane: the part carries data-depth=overlay, and [data-depth=overlay] declares this property at the same specificity (0,1,0) and LATER in the cascade, so the recipe key is bypassed (see next-features 12.9, measured on tooltip, popover and float-panel)';
export const SENTINEL_EXCEPTIONS: Record<string, Record<string, string>> = {
slider: {
// 2026-08-24. Seven keys, seven measured reasons, zero retirements: an
// orientation, a pointer held DOWN, two demo states and the transition
// pair the guard freezes. Every one reaches once its state exists — the
// contract does not lie, the stage only wears one of its faces.
'min-block-size':
"only [data-slider][data-orientation='vertical'] reads it, and the stage boots horizontal. Measured 2026-08-24 through the orientation chip of the demo: vertical -> reaches (block-size and min-block-size 160px -> 1234px)",
'active-thumb-scale':
'the pickup lift lives in `[data-slider-thumb]:active`, which needs the pointer HELD DOWN, and the static pass of the guard parks the pointer. Measured with a real mouse.down() on the real thumb, transitions frozen -> reaches (scale 1.15 -> 4.56)',
'active-thumb-shadow':
'same :active pickup, measured the same way -> reaches (rgba(15, 23, 42, 0.12) 0px 8px 24px -> rgb(1, 2, 3) 0px 0px 0px 7px)',
'active-tick-bg':
'a tick carries data-active only while its value sits INSIDE [min(values), max(values)] (soma SliderTickProvider.isActive), so one thumb at 40 with ticks at 0/50/100 leaves the three inactive — the token is not dead, its state is unreachable with a single value. Measured with the `multiple` chip of the demo (values 20-80, tick 50 goes active) -> reaches (oklch(0.5556 0.1829 305.86) -> rgb(1, 2, 3))',
'disabled-opacity':
'`[data-slider][data-disabled]`, and the stage boots enabled. Measured with the disabled toggle of the demo -> reaches (opacity 0.4 -> 0.123)',
'transition-duration':
'the guard freezes transitions and this token IS the transition; measured unfrozen -> reaches (0.12s -> 11.5s on the four transitioned properties of the thumb)',
'transition-ease':
'same freeze; measured unfrozen -> reaches (cubic-bezier(0.4, 0, 0.2, 1) -> steps(4))'
},
'scroll-area': {
// 2026-08-24. Three keys, three measured reasons, zero retirements: one
// MODE the demo has no control for, and the transition pair the guard

@ -7,6 +7,51 @@ Fecha de revision: 2026-05-17.
Air no tenia `slider` en `glm-5:src/uix/air/components`; solo habia iconos de
sliders. La referencia local es Soma/Morfo.
## Talla y tema
**39 claves públicas** en `lib/recipes/base.ts` (bloque `slider`), con el eje
`size` en cinco pasos (`xs`…`xl`). La receta **no consume la clave por talla
directamente**: cada eje dimensional entra por un privado resuelto
(`--_slider-{track,thumb,hit,tick}-size`) que los bloques `[data-slider][data-size]`
apuntan al paso en vigor — el patrón canónico de escala, y la razón de que sólo
UNA de las cinco pinte a la vez. La pestaña **Tokens** de su demo las resuelve
en vivo.
| Grupo | Claves |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| escalas | `track-size-{xs…xl}` · `thumb-size-{xs…xl}` · `hit-size-{xs…xl}` · `tick-size-{xs…xl}` |
| caja | `min-inline-size` · `min-block-size` · `disabled-opacity` |
| rail | `track-radius` · `track-bg` · `range-bg` · `secondary-bg` |
| thumb | `thumb-radius` · `thumb-border-width` · `thumb-border` · `thumb-bg` · `thumb-shadow` · `active-thumb-scale` · `active-thumb-shadow` |
| tick | `tick-radius` · `tick-bg` · `active-tick-bg` |
| transición | `transition-duration` · `transition-ease` |
`hit-size-{k}` es el ÁREA DE AGARRE (la altura del control), no el grosor de la
pintura: el rail se pinta con `track-size-{k}` sobre el `::before` de la raíz,
centrado dentro del `hit`. Son dos knobs a propósito — un rail de 6 px con 32 px
de agarre es el objetivo táctil, no un descuadre.
**Este contrato lo COMPONEN otros siete componentes**, que re-tiñen o
re-dimensionan estas mismas claves sobre su propio Slider embebido:
`media-player` y `skin-media-player` (barra de tiempo y volumen, incluida
`min-block-size` para el volumen vertical), `waveform` (su playhead ES este
thumb), `color-picker` y `gradient-builder` (los raíles de canal),
`image-adjustments` (el rail de tono) y `time-range-picker`. Ninguna clave se
retira ni se renombra sin barrer esos siete.
**Lo que el guard R-5.4 da por silencioso** (7 de 39, todas medidas y vivas,
ninguna retirada): `min-block-size` (sólo la orientación vertical la lee),
`active-thumb-scale` / `active-thumb-shadow` (piden el puntero MANTENIDO, y el
pase estático del guard lo aparca), `active-tick-bg` (un tick sólo se activa
dentro de `[min(valores), max(valores)]`, así que con un solo pulgar no hay tick
activo), `disabled-opacity` (el escenario arranca habilitado) y el par
`transition-duration` / `transition-ease`, que ES la transición que el guard
congela para poder medir lo demás.
**El único literal es identidad y va firmado**: el `inline-size: 100%` del rail
horizontal — un rail ocupa su contenedor; su suelo sí es un knob, y se llama
`min-inline-size`.
## Comparativa
| Referencia | Superficie relevante | Estado Eidos |

@ -67,7 +67,7 @@
}
[data-slider][data-orientation='horizontal'] {
inline-size: 100%;
inline-size: 100%; /* literal: a rail spans its container — identity; its floor is `min-inline-size` */
block-size: var(--_slider-hit-size);
min-inline-size: var(--slider-min-inline-size);
}

Loading…
Cancel
Save

Powered by TurnKey Linux.