Séptimo del bloque F2-A.
censo 0 % → 77 % · global 42 %
computed 2.842 valores en 7 estados: 0 diffs
**Los botones prev/next no se acuñan aquí** — componen `<IconButton>`, así que
su cromo es el del Button y un tema los viste por ahí. Esta receta sólo decide
DÓNDE se colocan (`trigger-offset`). El veredicto avisaba de comprobarlo antes
de copiar filas de trigger, y estaba en lo cierto.
**El ⚠ del informe eran DOS gaps distintos**, no un knob con dos valores: el
`gap` en columna de la raíz y el `item-gap` ENTRE DIAPOSITIVAS. Y el segundo
sólo se aparta del default en `xs`, así que su cascada declara UN override en
vez de cinco coordenadas iguales — el TSC no necesita que se le repita lo que
ya hereda.
**Los puntos del paginador son geometría propia**: 0.375–0.75rem por talla, ni
bundle ni desviación que marcar, porque el bundle no tiene coordenada que
signifique «un punto». El punto activo se estira a pastilla con un factor que
ahora es token (`active-indicator-scale`): es lo que lo hace leer como «estás
aquí» y no como un punto más gordo.
**El radio interior es concéntrico**, no un segundo radio: viewport y
diapositivas redondean por dentro del marco, así que su esquina es la del marco
menos el borde — el `2px` suelto pasa a `inner-radius-inset`.
Las tres variantes (surface / outline / ghost) entran enteras: padding del
marco, borde y superficie.
Quedan 5 literales de layout (`block-size: 100%` ×3 para que el viewport
vertical no colapse, `max-content` del raíl de puntos) y los 2 privados de
paleta.
audit PASS · eidos-lint 0 invalid · rtl 0 · docs 0 · check 0 en tocados ·
suite: sólo el rojo conocido
Demo con tab Tokens: 30 filas, 0 sin computar.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
_La receta no declara privados propios en su CSS._
Consumidos y **no declarados en el CSS** (vienen de `base.ts` o de un estilo inline del wrapper): `--_carousel-palette-element`, `--_carousel-palette-solid`.
## 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` (39)
### 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
@ -97,61 +63,13 @@ no distingue lo que debería — se marca `⚠`.
- **⚠ 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: `block-size`, `inline-size`.
- **⚠ decisión: `padding` es shorthand o eje físico — hay que partirlo en ejes lógicos antes de nombrarlo (recipe-contract §1, R-4.4)** — 2: `padding`.
- **⚠ decisión: `border` es shorthand o eje físico — hay que partirlo en ejes lógicos antes de nombrarlo (recipe-contract §1, R-4.4)** — 3: `border`.
- **⚠ 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`.
### 4.3 Avisos sobre los tokens propuestos (5)
- **el privado `--_carousel-vertical-block-size` debe pasar a leer este público (o desaparecer)** — `--carousel-height`
- **el privado `--_carousel-radius` debe pasar a leer este público (o desaparecer)** — `--carousel-surface-radius`, `--carousel-outline-radius`, `--carousel-viewport-radius`, `--carousel-item-radius`
- **el privado `--_carousel-gap` debe pasar a leer este público (o desaparecer)** — `--carousel-item-group-gap`
- **el privado `--_carousel-indicator-gap` debe pasar a leer este público (o desaparecer)** — `--carousel-indicator-group-gap-md`, `--carousel-indicator-group-gap-xs`, `--carousel-indicator-group-gap-sm`, `--carousel-indicator-group-gap-lg`, `--carousel-indicator-group-gap-xl`
- **el privado `--_carousel-indicator-size` debe pasar a leer este público (o desaparecer)** — `--carousel-indicator-width-md`, `--carousel-indicator-width-xs`, `--carousel-indicator-width-sm`, `--carousel-indicator-width-lg`, `--carousel-indicator-width-xl`, `--carousel-indicator-height-md`, `--carousel-indicator-height-xs`, `--carousel-indicator-height-sm`, `--carousel-indicator-height-lg`, `--carousel-indicator-height-xl`, `--carousel-indicator-group-width-md`, `--carousel-indicator-group-width-xs`, `--carousel-indicator-group-width-sm`, `--carousel-indicator-group-width-lg`, `--carousel-indicator-group-width-xl`, `--carousel-indicator-group-height-md`, `--carousel-indicator-group-height-xs`, `--carousel-indicator-group-height-sm`, `--carousel-indicator-group-height-lg`, `--carousel-indicator-group-height-xl`
### 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.
| Visual styling | Fuera de scope | Headless/data attrs | Tailwind recipe | Eidos recipe tokens |
Fuentes:
@ -60,11 +60,40 @@ Fuentes:
resuelven de esa misma fuente. Solo aplica al eje inline: en vertical los
chevrons son up/down y no giran. Es lo que hace shadcn con `rtl:rotate-180`.
## Talla y tema
Contrato en `lib/recipes/base.ts > carousel` (30 claves). Alcance del censo:
**77 %** (era 0 % antes del 2026-08-21).
**Los botones prev/next NO se tematizan desde aquí**: componen `<IconButton>`,
así que su cromo es el del Button y un tema los viste por ahí. Esta receta sólo
decide DÓNDE se colocan (`trigger-offset`).
**Los puntos del paginador son geometría propia.** Sus tamaños
(0.375–0.75rem por talla) no son ni bundle ni desviación que marcar: el bundle
no tiene coordenada que signifique «un punto». Van verbatim por talla, con su
nombre resuelto. El punto activo se estira a pastilla con
`active-indicator-scale` — el factor es lo que lo hace leer como «estás aquí» y
no como un punto más gordo.
**El ⚠ del informe eran DOS gaps distintos**, no uno con dos valores: el `gap`
en columna de la raíz y el `item-gap` ENTRE DIAPOSITIVAS, que además sólo se
aparta del default en `xs` — por eso su cascada declara un único override en
vez de cinco coordenadas iguales.
**El radio interior es concéntrico, no un segundo radio**: viewport y
diapositivas redondean por dentro del marco, así que su esquina es la del marco
menos el borde (`inner-radius-inset`).
`R-5.1 exception: block-size/inline-size: 100%`×3 y `max-content` — la cadena
de alturas que la orientación vertical necesita para que el viewport no
colapse, y el ancho del raíl de puntos. Mecánica de layout, no apariencia.
## Gaps
| Gap | Disposicion | Detalle |
| --- | --- | --- |
| Pause/play trigger publico dentro del componente | diferir | La API imperativa ya expone `play`, `pause` y `reset`; una parte visual requiere Morfo/Soma. |
| Labels traducidos para slide/indicator generados por indice | implementar en Soma | El README de Soma ya documenta que parte del texto se arma en JS. |
| Tests browser-level permanentes | implementar | El fallo de click sobre SVG se verifico manualmente con Playwright; conviene convertirlo en test visual si el harness lo permite. |
| Motion attrs por direccion | diferir | Seria un extra visual para animaciones internas de slide. |
| Pause/play trigger publico dentro del componente | diferir | La API imperativa ya expone `play`, `pause` y `reset`; una parte visual requiere Morfo/Soma. |
| Labels traducidos para slide/indicator generados por indice | implementar en Soma | El README de Soma ya documenta que parte del texto se arma en JS. |
| Tests browser-level permanentes | implementar | El fallo de click sobre SVG se verifico manualmente con Playwright; conviene convertirlo en test visual si el harness lo permite. |
| Motion attrs por direccion | diferir | Seria un extra visual para animaciones internas de slide. |