From e522e04e65eaa3d8fb303442aed87ab0f64a9c62 Mon Sep 17 00:00:00 2001 From: dev Date: Sun, 23 Aug 2026 19:05:58 +0200 Subject: [PATCH] =?UTF-8?q?docs(theming):=20los=2021=20de=20la=20ma=C3=B1a?= =?UTF-8?q?na=20recuperan=20su=20README=20y=20su=20pesta=C3=B1a=20Tokens?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La revisión de hoy (`REVIEW-theming-2026-08-23.md`, punto P4) destapó que NINGUNO de los commits de tokenización de la mañana del 23 hizo los pasos 8 y 9 del protocolo: `git show --stat` de los diecisiete sólo tocaba CSS, base.ts, el ledger y las fichas. Veintidós componentes tokenizados sin la tabla de tokens en su README y veintiuno sin la pestaña que la enseña viva. QUÉ ENTRA - **README «Talla y tema»** en 22 (los 21 con demo + `surface`, que no tiene ruta). La tabla NO está escrita a mano: se DERIVA de `lib/recipes/base.ts` y de `theming-sentinel-exceptions.ts`, así que lo que el lector ve es lo que el contrato dice. Hasta 30 claves va la tabla completa clave → valor por defecto; por encima, agrupada por parte (con la paleta en su propio grupo, que si no se come la tabla: button tiene 70 claves de tono de 106). Debajo, lo que el guard da por silencioso con su razón medida, y la excepción POR PATRÓN cuando la razón es la cascada de paleta. - **Pestaña `Tokens`** en los 21 con demo, con el conteo real de claves. VERIFICADO EN EL NAVEGADOR, LOS 21 Cada pestaña abre y lista exactamente sus claves: menubar 35 · field 68 · onion-menu 19 · button 106 · callout 34 · empty-state 26 · dropdown-menu 28 · context-menu 28 · checkbox 47 · image 23 · anchor-nav 12 · banner 53 · date-range-field 7 · time-range-field 7 · tooltip 23 · section 4 · sticky 1 · button-group 1 · qr-code 10 · toggle-group 1 · split-button 1. ⚠ Y el verificador mintió DOS veces antes de acertar: primero buscaba el rótulo de la cabecera del panel en `innerText` (no lo encontraba aunque la tabla estaba ahí), y después clicaba con `element.click()` tras `waitUntil: 'load'` — la página aún NO ha hidratado, así que el `onclick` de Svelte no está enganchado y el clic no hace nada. Con `networkidle` + el clic de Playwright (que espera a que el nodo sea accionable), los 21 en verde. Es la ley de siempre: el instrumento miente primero. `audio-player` queda fuera: no tiene README propio — hueco aparte, anotado. Verificación: `npm run check` sin errores nuevos en las 21 demos (los 72 globales son ajenos y preexistentes) · `docs:check` 0 · cada README conserva su estructura de encabezados y **ninguno gana un hunk de prettier** (mi sección se formateó dentro de su propio recorte, sin tocar lo ajeno). Co-Authored-By: Claude Opus 5 --- src/uix/eidos/components/anchor-nav/README.md | 21 +++++++++ src/uix/eidos/components/banner/README.md | 12 ++++++ .../eidos/components/button-group/README.md | 10 +++++ src/uix/eidos/components/button/README.md | 41 ++++++++++++++++++ src/uix/eidos/components/callout/README.md | 19 ++++++++ src/uix/eidos/components/checkbox/README.md | 34 +++++++++++++++ .../eidos/components/context-menu/README.md | 37 ++++++++++++++++ .../components/date-range-field/README.md | 16 +++++++ .../eidos/components/dropdown-menu/README.md | 37 ++++++++++++++++ .../eidos/components/empty-state/README.md | 35 +++++++++++++++ src/uix/eidos/components/field/README.md | 37 ++++++++++++++++ src/uix/eidos/components/image/README.md | 38 ++++++++++++++++ src/uix/eidos/components/menubar/README.md | 14 ++++++ src/uix/eidos/components/onion-menu/README.md | 36 ++++++++++++++++ src/uix/eidos/components/qr-code/README.md | 28 ++++++++++++ src/uix/eidos/components/section/README.md | 19 ++++++++ .../eidos/components/split-button/README.md | 10 +++++ src/uix/eidos/components/sticky/README.md | 10 +++++ src/uix/eidos/components/surface/README.md | 39 +++++++++++++++++ .../components/time-range-field/README.md | 16 +++++++ .../eidos/components/toggle-group/README.md | 10 +++++ src/uix/eidos/components/tooltip/README.md | 43 +++++++++++++++++++ .../uix/components/anchor-nav/+page.svelte | 11 ++++- web/routes/uix/components/banner/+page.svelte | 11 ++++- .../uix/components/button-group/+page.svelte | 11 ++++- web/routes/uix/components/button/+page.svelte | 11 ++++- .../uix/components/callout/+page.svelte | 11 ++++- .../uix/components/checkbox/+page.svelte | 11 ++++- .../uix/components/context-menu/+page.svelte | 11 ++++- .../components/date-range-field/+page.svelte | 11 ++++- .../uix/components/dropdown-menu/+page.svelte | 11 ++++- .../uix/components/empty-state/+page.svelte | 11 ++++- web/routes/uix/components/field/+page.svelte | 11 ++++- web/routes/uix/components/image/+page.svelte | 11 ++++- .../uix/components/menubar/+page.svelte | 11 ++++- .../uix/components/onion-menu/+page.svelte | 11 ++++- .../uix/components/qr-code/+page.svelte | 11 ++++- .../uix/components/section/+page.svelte | 11 ++++- .../uix/components/split-button/+page.svelte | 11 ++++- web/routes/uix/components/sticky/+page.svelte | 11 ++++- .../components/time-range-field/+page.svelte | 11 ++++- .../uix/components/toggle-group/+page.svelte | 11 ++++- .../uix/components/tooltip/+page.svelte | 11 ++++- 43 files changed, 772 insertions(+), 21 deletions(-) diff --git a/src/uix/eidos/components/anchor-nav/README.md b/src/uix/eidos/components/anchor-nav/README.md index 7e402f259..99ad18c3f 100644 --- a/src/uix/eidos/components/anchor-nav/README.md +++ b/src/uix/eidos/components/anchor-nav/README.md @@ -32,6 +32,27 @@ floor = v1). Headless behavior: spec-precise value for "current position within a page" (NOT `page`). Only 1 of 5 references sets `aria-current` at all. +## Talla y tema + +**12 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `anchor-nav`). +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--anchor-nav-…`) | Valor por defecto | +| ------------------------- | --------------------------------- | +| `indent` | `var(--space-3)` | +| `rail-width` | `2px` | +| `rail-fg` | `var(--color-border-subtle)` | +| `active-rail-fg` | `var(--color-primary-solid)` | +| `font-size` | `var(--size-sm-font-size)` | +| `line-height` | `var(--size-sm-font-line-height)` | +| `link-padding-block` | `var(--space-1)` | +| `link-radius` | `var(--radius-sm)` | +| `link-fg` | `var(--color-content-muted)` | +| `hover-link-fg` | `var(--color-content-primary)` | +| `active-link-fg` | `var(--color-primary-text)` | +| `active-link-font-weight` | `var(--font-weight-medium)` | + ## Comparativa | Ref | Qué adoptamos | Qué no | diff --git a/src/uix/eidos/components/banner/README.md b/src/uix/eidos/components/banner/README.md index e36e7632e..0b7b1c8db 100644 --- a/src/uix/eidos/components/banner/README.md +++ b/src/uix/eidos/components/banner/README.md @@ -52,6 +52,18 @@ Air's CSS prefix (`air-banner`) is dropped; selectors target `[data-banner]` directly. CSS variables renamed from `--air-banner-*` to `--banner-*` (public) and `--_banner-*` (internal recipe-local). +## Talla y tema + +**53 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `banner`), con sus pasos por talla y el nombre RESUELTO que consume la receta. +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Grupo | Claves | +| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `raíz` | `gap` · `radius` · `line-height` · `border-width` | +| `escalas` | `padding-block-sm` · `padding-block-md` · `padding-block-lg` · `padding-inline-sm` · `padding-inline-md` · `padding-inline-lg` · `font-size-sm` · `font-size-md` · `font-size-lg` | +| `paleta` | `primary-solid` · `primary-contrast` · `primary-track` · `primary-border` · `primary-text` · `secondary-solid` · `secondary-contrast` · `secondary-track` · `secondary-border` · `secondary-text` · `neutral-solid` · `neutral-contrast` · `neutral-track` · `neutral-border` · `neutral-text` · `affirm-solid` · `affirm-contrast` · `affirm-track` · `affirm-border` · `affirm-text` · `fulfill-solid` · `fulfill-contrast` · `fulfill-track` · `fulfill-border` · `fulfill-text` · `risk-solid` · `risk-contrast` · `risk-track` · `risk-border` · `risk-text` · `threat-solid` · `threat-contrast` · `threat-track` · `threat-border` · `threat-text` · `loss-solid` · `loss-contrast` · `loss-track` · `loss-border` · `loss-text` | + ## Comparativa | Capacidad | UIX (eidos) | Chakra UI Alert | Mantine Alert | MUI Alert | diff --git a/src/uix/eidos/components/button-group/README.md b/src/uix/eidos/components/button-group/README.md index 1064003b0..f1cf9211f 100644 --- a/src/uix/eidos/components/button-group/README.md +++ b/src/uix/eidos/components/button-group/README.md @@ -43,6 +43,16 @@ codebase: roving focus, `commit-toggle` event) with its own `ToggleGroup.Item`; ButtonGroup is **passive** and takes real standalone Buttons. +## Talla y tema + +**1 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `button-group`). +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--button-group-…`) | Valor por defecto | +| -------------------------- | ----------------- | +| `divider-strength` | `18%` | + ## Comparativa | Capability | Chakra v2 | MUI | Mantine | Bootstrap | Radix Themes | **UIX** | diff --git a/src/uix/eidos/components/button/README.md b/src/uix/eidos/components/button/README.md index 538fef259..3de02c8bc 100644 --- a/src/uix/eidos/components/button/README.md +++ b/src/uix/eidos/components/button/README.md @@ -70,6 +70,47 @@ font-size/font-weight/icon-size` por talla (`-xs`…`-xl`), `font-family`, que la cascada `--button-palette-*` resuelve según `data-color` (piloto del patrón; THEMING §25 admite escalas donantes per-instance). +## Talla y tema + +**106 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `button`), con sus pasos por talla y el nombre RESUELTO que consume la receta. +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Grupo | Claves | +| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `escalas` | `height-xs` · `height-sm` · `height-md` · `height-lg` · `height-xl` · `padding-inline-xs` · `padding-inline-sm` · `padding-inline-md` · `padding-inline-lg` · `padding-inline-xl` · `gap-xs` · `gap-sm` · `gap-md` · `gap-lg` · `gap-xl` · `font-size-xs` · `font-size-sm` · `font-size-md` · `font-size-lg` · `font-size-xl` · `font-weight-xs` · `font-weight-sm` · `font-weight-md` · `font-weight-lg` · `font-weight-xl` · `radius-sm` · `radius-md` · `radius-lg` · `radius-xl` · `radius-full` | +| `raíz` | `font-family` · `line-height` · `letter-spacing` · `border-width` · `shadow` · `transition-duration` · `transition-ease` | +| `icon` | `icon-size-xs` · `icon-size-sm` · `icon-size-md` · `icon-size-lg` · `icon-size-xl` | +| `estado` | `disabled-opacity` | +| `paleta` | `primary-track` · `primary-element` · `primary-border` · `primary-solid` · `primary-solid-hover` · `primary-text` · `primary-contrast` · `secondary-track` · `secondary-element` · `secondary-border` · `secondary-solid` · `secondary-solid-hover` · `secondary-text` · `secondary-contrast` · `neutral-track` · `neutral-element` · `neutral-border` · `neutral-solid` · `neutral-solid-hover` · `neutral-text` · `neutral-contrast` · `affirm-track` · `affirm-element` · `affirm-border` · `affirm-solid` · `affirm-solid-hover` · `affirm-text` · `affirm-contrast` · `fulfill-track` · `fulfill-element` · `fulfill-border` · `fulfill-solid` · `fulfill-solid-hover` · `fulfill-text` · `fulfill-contrast` · `risk-track` · `risk-element` · `risk-border` · `risk-solid` · `risk-solid-hover` · `risk-text` · `risk-contrast` · `threat-track` · `threat-element` · `threat-border` · `threat-solid` · `threat-solid-hover` · `threat-text` · `threat-contrast` · `loss-track` · `loss-element` · `loss-border` · `loss-solid` · `loss-solid-hover` · `loss-text` · `loss-contrast` · `palette-track` · `palette-element` · `palette-border` · `palette-solid` · `palette-solid-hover` · `palette-text` · `palette-contrast` | + +**Lo que el guard R-5.4 da por silencioso, con su razón medida** +(`scripts/theming-sentinel-exceptions.ts`): + +- `icon-size-xs` — the demo button carries no icon; a real child mounted and the size forced -> reaches (14px -> 123px) +- `icon-size-sm` — same, no icon in the demo; mounted -> reaches (16px -> 123px) +- `icon-size-md` — same, no icon in the demo; mounted -> reaches (18px -> 123px) +- `icon-size-lg` — same, no icon in the demo; mounted -> reaches (20px -> 123px) +- `icon-size-xl` — same, no icon in the demo; mounted -> reaches (32px -> 123px) +- `radius-sm` — the radius scale is an opt-in prop ([data-rounded]) and the demo does not set it; forced -> reaches (4px -> 1234px) +- `radius-lg` — same opt-in attribute; forced -> reaches (10px -> 1234px) +- `radius-xl` — same opt-in attribute; forced -> reaches (16px -> 1234px) +- `radius-full` — same opt-in attribute; forced data-rounded=full -> reaches (9999px -> 1234px) +- `transition-duration` — the guard freezes transitions to measure and this token IS the transition; measured unfrozen -> reaches (0.12s -> 11.5s, five properties) +- `transition-ease` — same instrument limit; measured unfrozen -> reaches (cubic-bezier(0.4, 0, 0.2, 1) -> steps(7)) +- `disabled-opacity` — no disabled button in the demo; forced data-disabled -> reaches (0.4 -> 0.137) +- `primary-track` — the FALLBACK of the palette forward: it acts only on an instance with NO data-color, and the demo stamps data-color=primary. Removed the attribute -> reaches. See the pattern entry below for… +- `primary-element` — same fallback, same condition +- `primary-border` — same fallback, same condition +- `primary-solid` — same fallback: without data-color it repaints (oklch(0.5556 0.1829 305.86) -> rgb(1,2,3)); with data-color=primary the generic forward rule supersedes it +- `primary-solid-hover` — same fallback, same condition +- `primary-text` — same fallback, same condition +- `primary-contrast` — same fallback, same condition +- `palette-track` — a RESOLVED name, declared on [data-button] by the forward, so a :root write loses BY DESIGN - a theme moves the tone or the scale. Measured on a soft button: from :root nothing, from the nod… +- `palette-element` — same resolved name; the theme moves its coordinate +- `palette-border` — same resolved name; the theme moves its coordinate +- **Por patrón** `/^(secondary|neutral|affirm|fulfill|risk|threat|loss)-(track|element|border|solid|solid-hover|text|contrast)$/` — la cascada de paleta: el bloque genérico `[data-button][data-color]` se emite el ÚLTIMO y gana por orden, así que la pintura sale del `--palette-*` global (§13, pendiente de firma). + ## Comparativa | Capacidad | Soma/Eidos | React Aria | Radix Themes | Chakra | Mantine | diff --git a/src/uix/eidos/components/callout/README.md b/src/uix/eidos/components/callout/README.md index ea8ebca65..b99c6f225 100644 --- a/src/uix/eidos/components/callout/README.md +++ b/src/uix/eidos/components/callout/README.md @@ -24,6 +24,25 @@ rule (parity floor = v1). 33 donor scales AND raw CSS colors resolve through the THM-2 shared layer with zero extra CSS. +## Talla y tema + +**34 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `callout`). +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Grupo | Claves | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `raíz` | `gap` · `padding` · `accent-width` · `radius` · `font-size` · `line-height` · `fg` | +| `row` | `row-gap` | +| `icon` | `icon-size` | +| `title` | `title-font-weight` | +| `paleta` | `primary-track` · `primary-text` · `primary-solid` · `secondary-track` · `secondary-text` · `secondary-solid` · `neutral-track` · `neutral-text` · `neutral-solid` · `affirm-track` · `affirm-text` · `affirm-solid` · `fulfill-track` · `fulfill-text` · `fulfill-solid` · `risk-track` · `risk-text` · `risk-solid` · `threat-track` · `threat-text` · `threat-solid` · `loss-track` · `loss-text` · `loss-solid` | + +**Lo que el guard R-5.4 da por silencioso, con su razón medida** +(`scripts/theming-sentinel-exceptions.ts`): + +- **Por patrón** `/^(primary|secondary|neutral|affirm|fulfill|risk|threat|loss)-(track|text|solid)$/` — la cascada de paleta: el bloque genérico `[data-callout][data-color]` se emite el ÚLTIMO y gana por orden, así que la pintura sale del `--palette-*` global (§13, pendiente de firma). + ## Comparativa | Ref | Equivalente | Qué adoptamos | Qué no | diff --git a/src/uix/eidos/components/checkbox/README.md b/src/uix/eidos/components/checkbox/README.md index fd4b30424..640fb7da8 100644 --- a/src/uix/eidos/components/checkbox/README.md +++ b/src/uix/eidos/components/checkbox/README.md @@ -23,6 +23,40 @@ Radix, Bits UI, Reka/Ark y shadcn-svelte. Partes publicas: `Indicator`, `HiddenInput`, `Group`, `GroupLabel`. +## Talla y tema + +**47 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `checkbox`). +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Grupo | Claves | +| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `raíz` | `size-xs-box-size` · `size-xs-indicator-size` · `size-xs-indicator-stroke` · `size-sm-box-size` · `size-sm-indicator-size` · `size-sm-indicator-stroke` · `size-md-box-size` · `size-md-indicator-size` · `size-md-indicator-stroke` · `size-lg-box-size` · `size-lg-indicator-size` · `size-lg-indicator-stroke` · `size-xl-box-size` · `size-xl-indicator-size` · `size-xl-indicator-stroke` · `radius` · `border-width` · `transition-duration` · `transition-ease` · `stroke-duration` · `stroke-ease` · `bg-off` · `border-off` · `group-gap` · `group-label-font-family` · `group-label-font-size` · `group-label-font-weight` · `group-label-line-height` · `group-label-fg` | +| `estado` | `invalid-border` · `invalid-ring` · `invalid-ring-gap` · `hover-border-off` · `disabled-bg` · `disabled-border` · `disabled-opacity` · `disabled-indicator-fg` · `disabled-group-label-fg` | +| `indicator` | `indicator-fg` | +| `paleta` | `primary-solid` · `primary-solid-hover` · `neutral-solid` · `neutral-solid-hover` · `secondary-solid` · `secondary-solid-hover` · `affirm-solid` · `affirm-solid-hover` | + +**Lo que el guard R-5.4 da por silencioso, con su razón medida** +(`scripts/theming-sentinel-exceptions.ts`): + +- `size-xs-indicator-stroke` — the glyph exists only inside a CHECKED box and the first checkbox of the demo is empty; measured on a checked one with data-size forced -> reaches (2px -> 7px) +- `size-sm-indicator-stroke` — same, forced -> reaches (2px -> 7px) +- `size-md-indicator-stroke` — same, forced -> reaches (2px -> 7px) +- `size-lg-indicator-stroke` — same, forced -> reaches (2px -> 7px) +- `size-xl-indicator-stroke` — same, forced -> reaches (2px -> 7px) +- `invalid-border` — only under [data-invalid]; forced -> reaches (oklch(0.9555 0.0207 13.86) -> rgb(1,2,3)) +- `invalid-ring` — the invalid focus ring: needs [data-invalid] AND :focus-visible, which the guard blurs on purpose; focused by hand -> reaches (the 4px ring turns rgb(1,2,3)) +- `invalid-ring-gap` — same double ring; forced -> reaches (the 2px gap turns rgb(4,5,6)) +- `disabled-bg` — only under [data-disabled]; forced -> reaches +- `disabled-border` — only under [data-disabled]; forced -> reaches +- `disabled-opacity` — only under [data-disabled]; forced -> reaches (0.4 -> 0.137) +- `disabled-indicator-fg` — needs [data-disabled] AND a checked box (the glyph); forced on a checked one -> reaches +- `disabled-group-label-fg` — the label carries its OWN [data-disabled] - it is not inherited from the group, so forcing the group does nothing; set on the label -> reaches (oklch(0.5032 0 0) -> rgb(1,2,3)) +- `transition-duration` — the guard freezes transitions and this token IS the transition; measured unfrozen -> reaches (0.12s -> 11.5s) +- `transition-ease` — same instrument limit; measured unfrozen -> reaches +- `stroke-duration` — same, on the check path dash animation; measured unfrozen -> reaches (0.12s -> 11.5s) +- **Por patrón** `/^(primary|secondary|neutral|affirm)-(solid|solid-hover)$/` — la cascada de paleta: el bloque genérico `[data-checkbox][data-color]` se emite el ÚLTIMO y gana por orden, así que la pintura sale del `--palette-*` global (§13, pendiente de firma). + ## Comparativa | Capacidad | Eidos/Soma | APG | Radix | Bits UI | Reka/Ark | shadcn-svelte | diff --git a/src/uix/eidos/components/context-menu/README.md b/src/uix/eidos/components/context-menu/README.md index 6cb1d3ea6..bd4645eec 100644 --- a/src/uix/eidos/components/context-menu/README.md +++ b/src/uix/eidos/components/context-menu/README.md @@ -68,6 +68,43 @@ Soma owns: - Same keyboard navigation as DropdownMenu inside the open Content - Focus management on open / close / sub navigation +## Talla y tema + +**28 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `context-menu`). +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--context-menu-…`) | Valor por defecto | +| ---------------------------- | -------------------------------- | +| `content-fg` | `var(--color-content-primary)` | +| `item-fg` | `var(--color-content-primary)` | +| `item-line-height` | `var(--leading-ui)` | +| `chevron-stroke` | `var(--border-width-medium)` | +| `heading-fg` | `var(--color-content-muted)` | +| `heading-font-weight` | `var(--style-label-font-weight)` | +| `heading-letter-spacing` | `var(--tracking-caps)` | +| `open-trigger-outline-width` | `var(--border-width)` | +| `open-trigger-outline` | `var(--color-border-default)` | +| `open-trigger-radius` | `var(--radius-sm)` | +| `content-min-width` | `12rem` | +| `content-max-height` | `min(60vh, 22rem)` | +| `content-padding` | `var(--space-1)` | +| `content-radius` | `var(--radius-md)` | +| `content-font-size` | `var(--size-sm-font-size)` | +| `item-gap` | `var(--space-2)` | +| `item-height` | `2rem` | +| `item-padding-inline` | `var(--space-2)` | +| `item-padding-block` | `var(--space-1)` | +| `item-radius` | `var(--radius-sm)` | +| `hover-item-bg` | `var(--color-primary-element)` | +| `hover-item-fg` | `var(--color-content-primary)` | +| `item-disabled-opacity` | `0.55` | +| `heading-padding-inline` | `var(--space-2)` | +| `heading-padding-block` | `var(--space-1)` | +| `heading-font-size` | `var(--size-xs-font-size)` | +| `separator-bg` | `var(--color-neutral-separator)` | +| `separator-margin-block` | `var(--space-1)` | + ## Comparativa | Lib | Trigger source | Long-press (touch) | Shift+F10 | Sub-menus | Cursor anchor | diff --git a/src/uix/eidos/components/date-range-field/README.md b/src/uix/eidos/components/date-range-field/README.md index faf98c8d6..fd298b81f 100644 --- a/src/uix/eidos/components/date-range-field/README.md +++ b/src/uix/eidos/components/date-range-field/README.md @@ -82,6 +82,22 @@ WAI-ARIA Spinbutton pattern (per segment): Soma owns: segment focus / arrow stepping per endpoint, paste distribution, validation, hidden form inputs (ISO date strings). +## Talla y tema + +**7 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `date-range-field`). +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--date-range-field-…`) | Valor por defecto | +| ------------------------------ | ------------------------------ | +| `column-gap` | `var(--space-3)` | +| `row-gap` | `var(--space-1-5)` | +| `label-fg` | `var(--color-content-primary)` | +| `label-font-size` | `var(--size-sm-font-size)` | +| `label-font-weight` | `var(--font-weight-regular)` | +| `separator-fg` | `var(--color-content-muted)` | +| `separator-glyph` | `"'—'"` | + ## Comparativa | Lib | Two endpoints | Shared validate | Segment scoping | Range tint | diff --git a/src/uix/eidos/components/dropdown-menu/README.md b/src/uix/eidos/components/dropdown-menu/README.md index 3f2121c94..559cce978 100644 --- a/src/uix/eidos/components/dropdown-menu/README.md +++ b/src/uix/eidos/components/dropdown-menu/README.md @@ -122,6 +122,43 @@ ContextMenu has its own recipe; Menubar's per-menu panel already carries `data-dropdown-menu-content` and re-uses `DropdownMenu.Item`, so it inherits the rhythm + the item preset and only adds the `[data-stagger]` marker. +## Talla y tema + +**28 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `dropdown-menu`). +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--dropdown-menu-…`) | Valor por defecto | +| --------------------------- | --------------------------------- | +| `content-z` | `var(--z-index-overlay-floating)` | +| `content-fg` | `var(--color-content-primary)` | +| `item-fg` | `var(--color-content-primary)` | +| `item-line-height` | `var(--leading-ui)` | +| `chevron-stroke` | `var(--border-width-medium)` | +| `chevron-size` | `0.625rem` | +| `heading-fg` | `var(--color-content-muted)` | +| `heading-font-weight` | `var(--style-label-font-weight)` | +| `heading-letter-spacing` | `var(--tracking-caps)` | +| `separator-thickness` | `var(--border-width)` | +| `content-min-width` | `12rem` | +| `content-max-height` | `min(60vh, 22rem)` | +| `content-padding` | `var(--space-1)` | +| `content-radius` | `var(--radius-md)` | +| `content-font-size` | `var(--size-sm-font-size)` | +| `item-gap` | `var(--space-2)` | +| `item-height` | `2rem` | +| `item-padding-inline` | `var(--space-2)` | +| `item-padding-block` | `var(--space-1)` | +| `item-radius` | `var(--radius-sm)` | +| `hover-item-bg` | `var(--color-primary-element)` | +| `hover-item-fg` | `var(--color-content-primary)` | +| `item-disabled-opacity` | `0.55` | +| `heading-padding-inline` | `var(--space-2)` | +| `heading-padding-block` | `var(--space-1)` | +| `heading-font-size` | `var(--size-xs-font-size)` | +| `separator-bg` | `var(--color-neutral-separator)` | +| `separator-margin-block` | `var(--space-1)` | + ## Comparativa | Lib | Sub-menus | CheckboxItem / RadioItem | CheckboxGroup | Arrow | Modal toggle | diff --git a/src/uix/eidos/components/empty-state/README.md b/src/uix/eidos/components/empty-state/README.md index 20b5c7931..cfe2a440b 100644 --- a/src/uix/eidos/components/empty-state/README.md +++ b/src/uix/eidos/components/empty-state/README.md @@ -26,6 +26,41 @@ reference floor fixed by the research dossier the title reads ONE discrete bundle size above the component size (visual hierarchy decoupled from the semantic `level`). +## Talla y tema + +**26 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `empty-state`), con sus pasos por talla y el nombre RESUELTO que consume la receta. +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--empty-state-…`) | Valor por defecto | +| -------------------------- | --------------------------------- | +| `gap` | `var(--space-3)` | +| `actions-gap` | `var(--space-2)` | +| `media-bg` | `var(--color-neutral-track)` | +| `media-fg` | `var(--color-content-muted)` | +| `media-radius` | `var(--radius-lg)` | +| `description-measure` | `45ch` | +| `padding-block-sm` | `var(--space-4)` | +| `padding-block-md` | `var(--space-8)` | +| `padding-block-lg` | `var(--space-12)` | +| `padding-inline-sm` | `var(--space-3)` | +| `padding-inline-md` | `var(--space-4)` | +| `padding-inline-lg` | `var(--space-5)` | +| `title-font-size-sm` | `var(--size-md-font-size)` | +| `title-font-size-md` | `var(--size-lg-font-size)` | +| `title-font-size-lg` | `var(--size-xl-font-size)` | +| `description-font-size-sm` | `var(--size-sm-font-size)` | +| `description-font-size-md` | `var(--size-md-font-size)` | +| `description-font-size-lg` | `var(--size-md-font-size)` | +| `media-glyph-size-sm` | `var(--size-sm-icon-size)` | +| `media-glyph-size-md` | `var(--size-lg-icon-size)` | +| `media-glyph-size-lg` | `var(--size-xl-icon-size)` | +| `title-font-weight` | `var(--font-weight-semibold)` | +| `title-line-height` | `var(--size-sm-font-line-height)` | +| `title-fg` | `var(--color-content-primary)` | +| `description-line-height` | `var(--size-md-font-line-height)` | +| `description-fg` | `var(--color-content-muted)` | + ## Comparativa | Ref | Anatomy | What we adopted | What we didn't | diff --git a/src/uix/eidos/components/field/README.md b/src/uix/eidos/components/field/README.md index dfd364870..fc6814323 100644 --- a/src/uix/eidos/components/field/README.md +++ b/src/uix/eidos/components/field/README.md @@ -54,6 +54,43 @@ alinearse con el contrato Soma/Morfo. | Visual orientation | Eidos | `vertical`, `horizontal`, `responsive` | | Intent color | Eidos | Focus/required accent; invalid sigue usando estado de error | +## Talla y tema + +**68 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `field`), con sus pasos por talla y el nombre RESUELTO que consume la receta. +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Grupo | Claves | +| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `escalas` | `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` · `control-gap-xs` · `control-gap-sm` · `control-gap-md` · `control-gap-lg` · `control-gap-xl` · `control-font-size-xs` · `control-font-size-sm` · `control-font-size-md` · `control-font-size-lg` · `control-font-size-xl` | +| `raíz` | `font-family` · `floating-label-top` · `floating-label-padding-inline` · `layout-column-gap` · `required-fg` · `optional-fg` · `optional-font-weight` · `control-line-height` · `control-font-weight` · `control-radius` · `control-border-width` · `control-border` · `control-bg` · `control-ghost-border` · `control-ghost-bg` · `control-bg-readonly` · `control-fg` · `control-placeholder-fg` · `affix-fg` · `control-trigger-size` · `control-trigger-radius` · `control-trigger-fg` · `message-line-height` · `helper-fg` · `error-fg` · `transition-duration` · `transition-ease` | +| `label` | `label-gap` · `label-font-weight` · `label-line-height` · `label-fg` | +| `estado` | `invalid-label-fg` · `disabled-label-fg` · `hover-control-border` · `focus-control-border` · `invalid-control-border` · `disabled-control-bg` · `hover-control-trigger-fg` · `focus-control-trigger-fg` · `disabled-opacity` | +| `segment` | `segment-height` · `segment-active-bg` · `segment-active-text` | + +**Lo que el guard R-5.4 da por silencioso, con su razón medida** +(`scripts/theming-sentinel-exceptions.ts`): + +- `invalid-label-fg` — only under [data-invalid] and the demo boots valid; forced -> reaches (oklch(0.5855 0.1743 42.74) -> rgb(1,2,3)) +- `disabled-label-fg` — only under [data-disabled]; forced -> reaches (oklch(0.7921 0 0) -> rgb(1,2,3)) +- `invalid-control-border` — only under [data-invalid]; forced -> reaches (oklch(0.8059 0.1123 59.96) -> rgb(1,2,3)) +- `disabled-control-bg` — only under [data-disabled]; forced -> reaches (oklch(0.9551 0 0) -> rgb(1,2,3)) +- `control-bg-readonly` — only under [data-readonly]; forced -> reaches (oklch(0.9551 0 0) -> rgb(1,2,3)) +- `disabled-opacity` — it lives on the CONTROL, not on the field root, so the guard read the wrong node; forced data-disabled and read on the control -> reaches (0.4 -> 0.137) +- `control-ghost-border` — the ghost variant and the demo boots surface; forced data-variant=ghost -> reaches (transparent -> rgb(1,2,3)) +- `control-ghost-bg` — same ghost variant; forced -> reaches (transparent -> rgb(1,2,3)) +- `layout-column-gap` — only in the horizontal orientation; forced data-orientation=horizontal -> reaches (16px -> 1234px) +- `focus-control-border` — only under :focus-within, and the guard blurs ON PURPOSE (the click-focus poisoning fix); focused from the keyboard -> reaches (the focus ring colour -> rgb(1,2,3)) +- `focus-control-trigger-fg` — only under :focus-visible on the picker trigger, which the guard blurs; focused from the keyboard on /date-picker -> reaches (oklch(0.2435 0 0) -> rgb(1,2,3)) +- `floating-label-top` — floatingLabel is a demo switch that boots OFF, and the label must also be floated (focused or filled); switch on + focus -> reaches (0px -> 1234px) +- `floating-label-padding-inline` — same switch; turned on -> reaches (4px -> 1234px) +- `error-fg` — the error text only RENDERS when the field is invalid, and it is the demo switch that mounts it - forcing the data-invalid attribute does not make Svelte render the node; switch on -> reache… +- `control-placeholder-fg` — the ::placeholder box exists only when the input HAS a placeholder attribute, and the demo input has none: getComputedStyle then returns the ELEMENT style and the token reads dead. With a pl… +- `segment-active-bg` — the ACTIVE segment being edited: no segment on the field route and none focused; measured on /date-field with the segment clicked -> reaches (the 40% mix -> rgb(1,2,3)) +- `segment-active-text` — same segment; measured on /date-field -> reaches (oklch(0.5168 0.1733 305.88) -> rgb(1,2,3)) +- `segment-height` — a FAMILY token that field OWNS and the pickers CONSUME - nothing on the field routes reads it - and it is RESOLVED (declared per [data-field][data-size]), so a :root write loses BY DESIGN: a… +- `transition-duration` — the guard freezes transitions to measure and this token IS the transition; measured unfrozen -> reaches (0.12s -> 11.5s) + ## Comparativa externa | Plataforma | Modelo | Eidos/UIX | diff --git a/src/uix/eidos/components/image/README.md b/src/uix/eidos/components/image/README.md index 5cb080dbf..8cbead954 100644 --- a/src/uix/eidos/components/image/README.md +++ b/src/uix/eidos/components/image/README.md @@ -45,6 +45,44 @@ estado + passthrough nativo completo. `placeholderColor` (fondo mientras carga), `width`/`height`. - Textos localizados: `loading` / `error` para AT. +## Talla y tema + +**23 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `image`), con sus pasos por talla y el nombre RESUELTO que consume la receta. +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--image-…`) | Valor por defecto | +| ---------------------- | -------------------------------- | +| `size-xs` | `64px` | +| `size-sm` | `96px` | +| `size-md` | `160px` | +| `size-lg` | `240px` | +| `size-xl` | `360px` | +| `radius-none` | `0` | +| `radius-sm` | `var(--radius-sm)` | +| `radius-md` | `var(--radius-md)` | +| `radius-lg` | `var(--radius-lg)` | +| `radius-full` | `var(--radius-full)` | +| `fade-duration` | `var(--duration-normal)` | +| `fade-ease` | `var(--ease-out)` | +| `placeholder-base` | `var(--color-surface-raised)` | +| `skeleton-bg` | `var(--gradient-shimmer)` | +| `shimmer-duration` | `1.8s` | +| `font-family` | `var(--style-label-font-family)` | +| `fallback-fg` | `var(--color-content-secondary)` | +| `fallback-font-size` | `var(--size-sm-font-size)` | +| `fallback-line-height` | `var(--leading-ui)` | +| `error-bg` | `var(--color-surface-raised)` | +| `error-fg` | `var(--color-content-muted)` | +| `error-font-size` | `var(--size-sm-font-size)` | +| `error-line-height` | `var(--leading-ui)` | + +**Lo que el guard R-5.4 da por silencioso, con su razón medida** +(`scripts/theming-sentinel-exceptions.ts`): + +- `fade-duration` — the guard freezes transitions and this token IS the fade; measured unfrozen 2026-08-23 -> reaches (0.18s -> 11.5s) +- `fade-ease` — same instrument limit; measured unfrozen -> reaches (cubic-bezier(0, 0, 0.2, 1) -> steps(7)) + ## Comparativa | Capacidad | UIX | Radix Avatar | Chakra Image | Next/Image | diff --git a/src/uix/eidos/components/menubar/README.md b/src/uix/eidos/components/menubar/README.md index 08c90e08b..a15bab892 100644 --- a/src/uix/eidos/components/menubar/README.md +++ b/src/uix/eidos/components/menubar/README.md @@ -53,6 +53,20 @@ las partes internas por-menú ya no son propias — son re-exports de entre triggers; Home/End extremos; dentro del menú rige el teclado de DropdownMenu. +## Talla y tema + +**35 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `menubar`), con sus pasos por talla y el nombre RESUELTO que consume la receta. +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Grupo | Claves | +| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `raíz` | `bg` · `border-fg` · `border-width` · `radius` | +| `escalas` | `gap-sm` · `gap-md` · `gap-lg` · `padding-sm` · `padding-md` · `padding-lg` · `height-sm` · `height-md` · `height-lg` | +| `trigger` | `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` | +| `estado` | `open-trigger-bg` · `open-trigger-fg` · `disabled-trigger-fg` | +| `panel` | `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` | + ## Comparativa | Capacidad | UIX | Radix | Bits UI | shadcn | React Aria | diff --git a/src/uix/eidos/components/onion-menu/README.md b/src/uix/eidos/components/onion-menu/README.md index 7fde59f8e..0c486f530 100644 --- a/src/uix/eidos/components/onion-menu/README.md +++ b/src/uix/eidos/components/onion-menu/README.md @@ -161,6 +161,42 @@ APG (el morfo lo cita): trigger `aria-haspopup` → `role="menu"` de `menuitem`s; la geometría radial y el color por profundidad salen de los engines del framework. +## Talla y tema + +**19 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `onion-menu`). +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--onion-menu-…`) | Valor por defecto | +| ------------------------- | -------------------------------- | +| `trigger-lift` | `var(--fab-lift)` | +| `trigger-shadow` | `var(--fab-shadow)` | +| `trigger-radius` | `var(--radius-full)` | +| `trigger-fg` | `var(--color-content-on-solid)` | +| `sector-shadow` | `var(--shadow-raised)` | +| `sector-ring-fg` | `var(--color-content-on-solid)` | +| `sector-ring-width` | `2.5` | +| `sector-hover-ring-width` | `2` | +| `label-font-family` | `var(--style-label-font-family)` | +| `label-font-weight` | `var(--style-label-font-weight)` | +| `glyph-size` | `42%` | +| `glyph-bar-thickness` | `2px` | +| `glyph-bar-radius` | `var(--radius-full)` | +| `muted-opacity` | `0.85` | +| `hover-ring-opacity` | `0.65` | +| `rim-width` | `2` | +| `rim-glow-width` | `9` | +| `rim-glow-opacity` | `var(--opacity-45)` | +| `rim-glow-blur` | `var(--blur-sm)` | + +**Lo que el guard R-5.4 da por silencioso, con su razón medida** +(`scripts/theming-sentinel-exceptions.ts`): + +- `trigger-lift` — the lift TRANSITIONS, so an immediate read after the write returns the old value; hovered with transitions frozen -> reaches (translate 0 -2px -> 0 -123px) +- `rim-width` — the luminous look is not rendered by the component demo; measured on /active/docs/agnt -> reaches (2px -> 17px) +- `rim-glow-width` — same look, same route -> reaches (9px -> 17px) +- `rim-glow-blur` — same look, same route -> reaches (blur(4px) -> blur(13px)) + ## Comparativa | Capacidad | UIX | Pie menus (Blender/juegos) | Marking menus | Radix/Ark/RAC | diff --git a/src/uix/eidos/components/qr-code/README.md b/src/uix/eidos/components/qr-code/README.md index 712593777..882c57044 100644 --- a/src/uix/eidos/components/qr-code/README.md +++ b/src/uix/eidos/components/qr-code/README.md @@ -11,6 +11,34 @@ Themeable, accessible QR code — **own zero-dependency encoder**, framework No Air baseline — new component (2026-06-12). Nothing in the legacy layers rendered QR codes; the encoder itself is also new (`$libs/qr`, zero-dep). +## Talla y tema + +**10 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `qr-code`), con sus pasos por talla y el nombre RESUELTO que consume la receta. +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--qr-code-…`) | Valor por defecto | +| --------------------- | ------------------ | +| `fg` | `#18181b` | +| `bg` | `#ffffff` | +| `size-xs` | `96px` | +| `size-sm` | `128px` | +| `size-md` | `160px` | +| `size-lg` | `200px` | +| `size-xl` | `256px` | +| `radius` | `var(--radius-md)` | +| `overlay-bg` | `#ffffff` | +| `overlay-radius` | `var(--radius-sm)` | + +**Lo que el guard R-5.4 da por silencioso, con su razón medida** +(`scripts/theming-sentinel-exceptions.ts`): + +- `size-xs` — one step per instance: the wrapper writes var(--qr-code-size-{k}) inline from the size prop and the demo runs lg. Forced -> reaches (96px -> 123px) +- `size-sm` — same, one step per instance +- `size-md` — same, one step per instance +- `size-xl` — same, one step per instance +- `fg` — painted as the SVG fill of the module path, not as color on the root; read on the path -> reaches (rgb(24,24,27) -> rgb(1,2,3)) + ## Comparativa — why a new one (vs the references) | Capability | ark-ui (zag + `uqr`) | qr-code-styling | react-qr-code | **QrCode (ours)** | diff --git a/src/uix/eidos/components/section/README.md b/src/uix/eidos/components/section/README.md index 2c1f459b8..b5cd6ccf9 100644 --- a/src/uix/eidos/components/section/README.md +++ b/src/uix/eidos/components/section/README.md @@ -28,6 +28,25 @@ Origen: `air/components/layout/section`. Adaptación estándar. `region` sólo cuando lleva `aria-label`/`aria-labelledby`, que es el default correcto para una página que apila varias. +## Talla y tema + +**4 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `section`), con sus pasos por talla y el nombre RESUELTO que consume la receta. +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--section-…`) | Valor por defecto | +| --------------------- | ----------------------------- | +| `padding-block-sm` | `var(--space-8)` | +| `padding-block-md` | `var(--space-12)` | +| `padding-block-lg` | `var(--space-16)` | +| `padding-block-xl` | `calc(var(--space-16) * 1.5)` | + +**Lo que el guard R-5.4 da por silencioso, con su razón medida** +(`scripts/theming-sentinel-exceptions.ts`): + +- `padding-block-sm` — one step per instance; the demo runs md. Forced the step inline -> reaches +- `padding-block-lg` — same, one step per instance + ## Comparativa | Capacidad | UIX | Radix Themes Section | Chakra | Mantine | diff --git a/src/uix/eidos/components/split-button/README.md b/src/uix/eidos/components/split-button/README.md index 940eadccb..4e4ee9d8d 100644 --- a/src/uix/eidos/components/split-button/README.md +++ b/src/uix/eidos/components/split-button/README.md @@ -34,6 +34,16 @@ components — nothing reinvented: icon-only Button) + the menu (`.Content` → ``, `.Item`, …). - **``** — the default ▾ glyph (rotates while open). +## Talla y tema + +**1 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `split-button`). +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--split-button-…`) | Valor por defecto | +| -------------------------- | ----------------- | +| `trigger-padding-inline` | `var(--space-1)` | + ## Comparativa | Capability | Fluent UI | Ant `Dropdown.Button` | PrimeReact | Bootstrap | MUI (recipe) | **UIX** | diff --git a/src/uix/eidos/components/sticky/README.md b/src/uix/eidos/components/sticky/README.md index 015999177..2f51599ac 100644 --- a/src/uix/eidos/components/sticky/README.md +++ b/src/uix/eidos/components/sticky/README.md @@ -30,6 +30,16 @@ Reference floor + reflow doctrine: the research dossier blesses; `uix.perf`'s reflow detector can prove the demo does zero forced-reflow — a measurable quality claim no reference library makes. +## Talla y tema + +**1 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `sticky`). +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--sticky-…`) | Valor por defecto | +| -------------------- | ----------------------- | +| `z-index` | `var(--z-index-sticky)` | + ## Comparativa | Ref | Equivalente | Qué adoptamos | Qué no | diff --git a/src/uix/eidos/components/surface/README.md b/src/uix/eidos/components/surface/README.md index ff7bed93e..68bcaaa4a 100644 --- a/src/uix/eidos/components/surface/README.md +++ b/src/uix/eidos/components/surface/README.md @@ -115,6 +115,45 @@ espacio de props de soma y clobbeara el estampado). - **Custom color** (`data-color-custom`) — **diferir**: la vía existe en Card si surge el caso real. +## Talla y tema + +**25 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `surface`). +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--surface-…`) | Valor por defecto | +| --------------------- | --------------------------------- | +| `radius` | `var(--radius-lg)` | +| `neutral-track` | `var(--color-neutral-track)` | +| `neutral-solid` | `var(--color-neutral-solid)` | +| `neutral-contrast` | `var(--color-neutral-contrast)` | +| `primary-track` | `var(--color-primary-track)` | +| `primary-solid` | `var(--color-primary-solid)` | +| `primary-contrast` | `var(--color-primary-contrast)` | +| `secondary-track` | `var(--color-secondary-track)` | +| `secondary-solid` | `var(--color-secondary-solid)` | +| `secondary-contrast` | `var(--color-secondary-contrast)` | +| `affirm-track` | `var(--color-affirm-track)` | +| `affirm-solid` | `var(--color-affirm-solid)` | +| `affirm-contrast` | `var(--color-affirm-contrast)` | +| `fulfill-track` | `var(--color-fulfill-track)` | +| `fulfill-solid` | `var(--color-fulfill-solid)` | +| `fulfill-contrast` | `var(--color-fulfill-contrast)` | +| `risk-track` | `var(--color-risk-track)` | +| `risk-solid` | `var(--color-risk-solid)` | +| `risk-contrast` | `var(--color-risk-contrast)` | +| `threat-track` | `var(--color-threat-track)` | +| `threat-solid` | `var(--color-threat-solid)` | +| `threat-contrast` | `var(--color-threat-contrast)` | +| `loss-track` | `var(--color-loss-track)` | +| `loss-solid` | `var(--color-loss-solid)` | +| `loss-contrast` | `var(--color-loss-contrast)` | + +**Lo que el guard R-5.4 da por silencioso, con su razón medida** +(`scripts/theming-sentinel-exceptions.ts`): + +- **Por patrón** `/^(primary|secondary|neutral|affirm|fulfill|risk|threat|loss)-(track|solid|contrast)$/` — la cascada de paleta: el bloque genérico `[data-surface][data-color]` se emite el ÚLTIMO y gana por orden, así que la pintura sale del `--palette-*` global (§13, pendiente de firma). + ## Comparativa | | UIX Surface | Chakra `Box bg=` | Radix Themes | MD3 | diff --git a/src/uix/eidos/components/time-range-field/README.md b/src/uix/eidos/components/time-range-field/README.md index d8e91b277..41f095132 100644 --- a/src/uix/eidos/components/time-range-field/README.md +++ b/src/uix/eidos/components/time-range-field/README.md @@ -63,6 +63,22 @@ Soma posee: composición de un TimeField real por endpoint (valor por slice, placeholder controlado compartido para que un endpoint no mueva el ancla del otro), validación de rango, flags mergeados con `Field.Provider` (OR). +## Talla y tema + +**7 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `time-range-field`). +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--time-range-field-…`) | Valor por defecto | +| ------------------------------ | ------------------------------ | +| `column-gap` | `var(--space-3)` | +| `row-gap` | `var(--space-1-5)` | +| `label-fg` | `var(--color-content-primary)` | +| `label-font-size` | `var(--size-sm-font-size)` | +| `label-font-weight` | `var(--font-weight-regular)` | +| `separator-fg` | `var(--color-content-muted)` | +| `separator-glyph` | `"'—'"` | + ## Comparativa | Lib | TimeRangeField dedicado | Endpoints segmentados | Validación de rango compartida | diff --git a/src/uix/eidos/components/toggle-group/README.md b/src/uix/eidos/components/toggle-group/README.md index 59fcbe949..b8bff757d 100644 --- a/src/uix/eidos/components/toggle-group/README.md +++ b/src/uix/eidos/components/toggle-group/README.md @@ -89,6 +89,16 @@ The group itself needs an accessible name (`aria-label` or `aria-labelledby`) per APG. Soma warns at mount in dev when both are missing. +## Talla y tema + +**1 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `toggle-group`). +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--toggle-group-…`) | Valor por defecto | +| -------------------------- | ----------------- | +| `gap` | `var(--space-1)` | + ## Comparativa | Lib | Selection | Variant | Color | Attached | Block | Notes | diff --git a/src/uix/eidos/components/tooltip/README.md b/src/uix/eidos/components/tooltip/README.md index a1c0f0a76..d24f2880b 100644 --- a/src/uix/eidos/components/tooltip/README.md +++ b/src/uix/eidos/components/tooltip/README.md @@ -7,6 +7,49 @@ Fecha de revision: 2026-05-17. Air no tenia `tooltip` en `glm-5:src/uix/air/components`; este componente es una envoltura visual sobre Soma/Morfo, no un port de Air. +## Talla y tema + +**23 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `tooltip`), con sus pasos por talla y el nombre RESUELTO que consume la receta. +Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas +claves y las resuelve sobre el escenario. + +| Token (`--tooltip-…`) | Valor por defecto | +| ---------------------- | -------------------------------------------------------------------------- | +| `content-z` | `var(--z-index-overlay-tooltip)` | +| `max-width` | `22rem` | +| `padding-block-sm` | `var(--space-1)` | +| `padding-inline-sm` | `var(--space-2)` | +| `padding-block-md` | `var(--space-1-5)` | +| `padding-inline-md` | `var(--space-2-5)` | +| `padding-block-lg` | `var(--space-2)` | +| `padding-inline-lg` | `var(--space-3)` | +| `font-size-sm` | `var(--size-sm-font-size)` | +| `font-size-md` | `var(--size-md-font-size)` | +| `font-size-lg` | `var(--size-lg-font-size)` | +| `font-family` | `var(--style-label-font-family)` | +| `font-weight` | `var(--font-weight-regular)` | +| `line-height` | `var(--leading-text)` | +| `radius` | `var(--radius-md)` | +| `border-width` | `var(--border-width)` | +| `bg` | `var(--color-surface-overlay)` | +| `fg` | `var(--color-content-primary)` | +| `border` | `color-mix( in srgb, var(--color-border-default) 84%, var(--tooltip-bg) )` | +| `shadow` | `var(--depth-overlay-shadow), var(--depth-overlay-halo)` | +| `ghost-blur` | `var(--blur-md)` | +| `outline-arrow-bg` | `var(--color-surface-default)` | +| `outline-arrow-border` | `var(--color-border-strong)` | + +**Lo que el guard R-5.4 da por silencioso, con su razón medida** +(`scripts/theming-sentinel-exceptions.ts`): + +- `content-z` — it lands on the floating WRAPPER, which carries no data-tooltip-\* attr and so is outside the measured set; read on the wrapper -> reaches (90 -> 4321) +- `bg` — SUPERSEDED by the overlay plane: [data-depth=overlay] declares background at the same specificity and later in the cascade, so the recipe loses. Measured: --tooltip-bg moves nothing, --depth… +- `border` — same supersession: --depth-overlay-border repaints it, --tooltip-border does not +- `shadow` — same supersession: --depth-overlay-shadow repaints it, --tooltip-shadow does not +- `font-family` — same plane, the typography half of it (PLAN 12.9, unsigned) +- `line-height` — same plane, same open decision +- `outline-arrow-bg` — the arrow is painted through a SIBLING selector that needs the content carrying data-variant=outline AND the panel open; measured with the demo switch -> reaches (oklch(0.9911 0 0) -> rgb(1,… + ## Comparativa | Referencia | Superficie relevante | Estado Eidos | diff --git a/web/routes/uix/components/anchor-nav/+page.svelte b/web/routes/uix/components/anchor-nav/+page.svelte index 579a6688b..c10250b78 100644 --- a/web/routes/uix/components/anchor-nav/+page.svelte +++ b/web/routes/uix/components/anchor-nav/+page.svelte @@ -8,11 +8,13 @@ import MotionPanel from '../../lib/MotionPanel.svelte'; import SemaPanel from '../../lib/SemaPanel.svelte'; import { DemoTrace } from '../../lib/harness.svelte'; + import TokensPanel from '../../lib/TokensPanel.svelte'; const uix = getActiveUix(); // prettier-ignore - type Tab = 'live' | 'system' | 'motion' | 'sema' | 'services' | 'api' | 'morfo' | 'recipe' | 'a11y'; + type Tab = 'live' | 'system' | 'motion' | 'sema' | 'services' | 'api' | 'morfo' | 'recipe' | 'tokens' + | 'a11y'; let tab = $state('live'); const trace = new DemoTrace(); @@ -173,6 +175,9 @@ + 12 + @@ -350,6 +355,10 @@ {/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/banner/+page.svelte b/web/routes/uix/components/banner/+page.svelte index 1fffff309..d721ec9ef 100644 --- a/web/routes/uix/components/banner/+page.svelte +++ b/web/routes/uix/components/banner/+page.svelte @@ -8,8 +8,10 @@ } from '$uix/eidos/components/banner'; import { compileMorfo } from '$uix/morfo'; import { bannerMorfo } from '@/uix/morfo/components/banner'; + import TokensPanel from '../../lib/TokensPanel.svelte'; - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; type TraceEntry = { event: string; family: string; intent?: string; at: number }; let tab = $state('live'); let trace = $state([]); @@ -201,6 +203,9 @@ {events.length} + @@ -453,6 +458,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/button-group/+page.svelte b/web/routes/uix/components/button-group/+page.svelte index fc69faf35..a42c7f7a9 100644 --- a/web/routes/uix/components/button-group/+page.svelte +++ b/web/routes/uix/components/button-group/+page.svelte @@ -9,8 +9,10 @@ import { Button } from '$uix/eidos/components/button'; import { compileMorfo } from '$uix/morfo'; import { buttonGroupMorfo } from '@/uix/morfo/components/button-group'; + import TokensPanel from '../../lib/TokensPanel.svelte'; - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; type TraceEntry = { event: string; family: string; intent?: string; at: number }; let tab = $state('live'); let trace = $state([]); @@ -184,6 +186,9 @@ + @@ -452,6 +457,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/button/+page.svelte b/web/routes/uix/components/button/+page.svelte index eb8731957..3a657f9ce 100644 --- a/web/routes/uix/components/button/+page.svelte +++ b/web/routes/uix/components/button/+page.svelte @@ -25,6 +25,7 @@ import MotionPanel from '../../lib/MotionPanel.svelte'; import SemaPanel from '../../lib/SemaPanel.svelte'; import { DemoTrace, PALETTE_SCALES } from '../../lib/harness.svelte'; + import TokensPanel from '../../lib/TokensPanel.svelte'; const uix = getActiveUix(); @@ -41,7 +42,8 @@ check: Icon.Check } as const; - type Tab = 'live' | 'system' | 'motion' | 'sema' | 'services' | 'api' | 'morfo' | 'recipe' | 'a11y'; + type Tab = 'live' | 'system' | 'motion' | 'sema' | 'services' | 'api' | 'morfo' | 'recipe' | 'tokens' + | 'a11y'; let tab = $state('live'); const variants: ButtonVariant[] = ['solid', 'soft', 'surface', 'outline', 'ghost', 'plain']; @@ -218,6 +220,9 @@ morfo{partsList.length}p · {actions.length}e + @@ -469,6 +474,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/callout/+page.svelte b/web/routes/uix/components/callout/+page.svelte index 328d72d62..a1a9d8caa 100644 --- a/web/routes/uix/components/callout/+page.svelte +++ b/web/routes/uix/components/callout/+page.svelte @@ -9,10 +9,12 @@ import MotionPanel from '../../lib/MotionPanel.svelte'; import SemaPanel from '../../lib/SemaPanel.svelte'; import { DemoTrace } from '../../lib/harness.svelte'; + import TokensPanel from '../../lib/TokensPanel.svelte'; const uix = getActiveUix(); - type Tab = 'live' | 'system' | 'motion' | 'sema' | 'services' | 'api' | 'morfo' | 'recipe' | 'a11y'; + type Tab = 'live' | 'system' | 'motion' | 'sema' | 'services' | 'api' | 'morfo' | 'recipe' | 'tokens' + | 'a11y'; let tab = $state('live'); // ── Stage + System axes ────────────────────────────────────────────── @@ -175,6 +177,9 @@ + @@ -478,6 +483,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/checkbox/+page.svelte b/web/routes/uix/components/checkbox/+page.svelte index 90c5fdddc..420ca5874 100644 --- a/web/routes/uix/components/checkbox/+page.svelte +++ b/web/routes/uix/components/checkbox/+page.svelte @@ -11,11 +11,13 @@ import { getActiveUix } from '$active-uix'; import { page } from '$app/state'; import { colorValue, PALETTE_SCALES } from '../../lib/harness.svelte'; + import TokensPanel from '../../lib/TokensPanel.svelte'; const uix = getActiveUix(); const params = page.url.searchParams; - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; let tab = $state('live'); // ── State ────────────────────────────────────────────────────────────── @@ -263,6 +265,9 @@ {events.length} + @@ -570,6 +575,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/context-menu/+page.svelte b/web/routes/uix/components/context-menu/+page.svelte index be33074a9..34891d950 100644 --- a/web/routes/uix/components/context-menu/+page.svelte +++ b/web/routes/uix/components/context-menu/+page.svelte @@ -3,10 +3,12 @@ import { compileMorfo } from '$uix/morfo'; import { contextMenuMorfo } from '@/uix/morfo/components/context-menu'; import { getActiveUix } from '$active-uix'; + import TokensPanel from '../../lib/TokensPanel.svelte'; const uix = getActiveUix(); - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; let tab = $state('live'); // ── Live state ──────────────────────────────────────────────────────── @@ -331,6 +333,9 @@ {events.length} + @@ -932,6 +937,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/date-range-field/+page.svelte b/web/routes/uix/components/date-range-field/+page.svelte index f32f43da3..44e8f1788 100644 --- a/web/routes/uix/components/date-range-field/+page.svelte +++ b/web/routes/uix/components/date-range-field/+page.svelte @@ -19,10 +19,12 @@ type HourCycle } from '$libs/days'; import { colorValue, PALETTE_SCALES } from '../../lib/harness.svelte'; + import TokensPanel from '../../lib/TokensPanel.svelte'; const uix = getActiveUix(); - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; type TraceEntry = { event: string; family: string; intent?: string; at: number }; type Direction = 'ltr' | 'rtl'; type ValueProfile = 'date' | 'datetime' | 'zoned'; @@ -462,6 +464,9 @@ {events.length} + @@ -954,6 +959,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/dropdown-menu/+page.svelte b/web/routes/uix/components/dropdown-menu/+page.svelte index c1bbd2628..7e28746e9 100644 --- a/web/routes/uix/components/dropdown-menu/+page.svelte +++ b/web/routes/uix/components/dropdown-menu/+page.svelte @@ -3,10 +3,12 @@ import { compileMorfo } from '$uix/morfo'; import { dropdownMenuMorfo } from '@/uix/morfo/components/dropdown-menu'; import { getActiveUix } from '$active-uix'; + import TokensPanel from '../../lib/TokensPanel.svelte'; const uix = getActiveUix(); - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; let tab = $state('live'); // ── Live state ──────────────────────────────────────────────────────── @@ -361,6 +363,9 @@ {events.length} + @@ -1043,6 +1048,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/empty-state/+page.svelte b/web/routes/uix/components/empty-state/+page.svelte index b34b5cdc3..21a423595 100644 --- a/web/routes/uix/components/empty-state/+page.svelte +++ b/web/routes/uix/components/empty-state/+page.svelte @@ -15,10 +15,12 @@ import MotionPanel from '../../lib/MotionPanel.svelte'; import SemaPanel from '../../lib/SemaPanel.svelte'; import { DemoTrace } from '../../lib/harness.svelte'; + import TokensPanel from '../../lib/TokensPanel.svelte'; const uix = getActiveUix(); - type Tab = 'live' | 'system' | 'motion' | 'sema' | 'services' | 'api' | 'morfo' | 'recipe' | 'a11y'; + type Tab = 'live' | 'system' | 'motion' | 'sema' | 'services' | 'api' | 'morfo' | 'recipe' | 'tokens' + | 'a11y'; let tab = $state('live'); // ── Stage + System axes ────────────────────────────────────────────── @@ -225,6 +227,9 @@ + @@ -522,6 +527,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/field/+page.svelte b/web/routes/uix/components/field/+page.svelte index 13a14239d..626aef6b2 100644 --- a/web/routes/uix/components/field/+page.svelte +++ b/web/routes/uix/components/field/+page.svelte @@ -8,8 +8,10 @@ } from '$uix/eidos/components/field'; import { compileMorfo } from '$uix/morfo'; import { fieldMorfo } from '@/uix/morfo/components/field'; + import TokensPanel from '../../lib/TokensPanel.svelte'; - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; type FieldState = 'idle' | 'error' | 'disabled' | 'readonly' | 'loading'; type TraceEntry = { event: string; family: string; intent?: string; at: number }; @@ -209,6 +211,9 @@ + @@ -481,6 +486,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/image/+page.svelte b/web/routes/uix/components/image/+page.svelte index 79fe0256b..e02e4d5ed 100644 --- a/web/routes/uix/components/image/+page.svelte +++ b/web/routes/uix/components/image/+page.svelte @@ -12,8 +12,10 @@ import { AspectRatio } from '$uix/eidos/components/aspect-ratio'; import { compileMorfo } from '$uix/morfo'; import { imageMorfo } from '@/uix/morfo/components/image'; + import TokensPanel from '../../lib/TokensPanel.svelte'; - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; type TraceEntry = { event: string; family: string; intent?: string; at: number }; let tab = $state('live'); let trace = $state([]); @@ -177,6 +179,9 @@ + @@ -898,6 +903,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/menubar/+page.svelte b/web/routes/uix/components/menubar/+page.svelte index 150d64973..a88b2c82c 100644 --- a/web/routes/uix/components/menubar/+page.svelte +++ b/web/routes/uix/components/menubar/+page.svelte @@ -9,10 +9,12 @@ import { compileMorfo } from '$uix/morfo'; import { menubarMorfo } from '@/uix/morfo/components/menubar'; import { getActiveUix } from '$active-uix'; + import TokensPanel from '../../lib/TokensPanel.svelte'; const uix = getActiveUix(); - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; let tab = $state('live'); // ── Live state ──────────────────────────────────────────────────────── @@ -433,6 +435,9 @@ {events.length} + @@ -752,6 +757,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/onion-menu/+page.svelte b/web/routes/uix/components/onion-menu/+page.svelte index b23a4ddf7..864d2162f 100644 --- a/web/routes/uix/components/onion-menu/+page.svelte +++ b/web/routes/uix/components/onion-menu/+page.svelte @@ -11,10 +11,12 @@ import { compileMorfo } from '$uix/morfo'; import { onionMenuMorfo } from '@/uix/morfo/components/onion-menu'; import { getActiveUix } from '$active-uix'; + import TokensPanel from '../../lib/TokensPanel.svelte'; const uix = getActiveUix(); - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; type TraceEntry = { event: string; family: string; intent?: string; at: number }; let tab = $state('live'); let trace = $state([]); @@ -253,6 +255,9 @@ + @@ -572,6 +577,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/qr-code/+page.svelte b/web/routes/uix/components/qr-code/+page.svelte index 7093781e6..2b0c4cd6f 100644 --- a/web/routes/uix/components/qr-code/+page.svelte +++ b/web/routes/uix/components/qr-code/+page.svelte @@ -7,8 +7,10 @@ } from '$uix/eidos/components/qr-code'; import { compileMorfo } from '$uix/morfo'; import { qrCodeMorfo } from '@/uix/morfo/components/qr-code'; + import TokensPanel from '../../lib/TokensPanel.svelte'; - type Tab = 'live' | 'examples' | 'api' | 'morfo' | 'recipe' | 'a11y'; + type Tab = 'live' | 'examples' | 'api' | 'morfo' | 'recipe' | 'tokens' + | 'a11y'; let tab = $state('live'); // The encoder takes ANY UTF-8 string — not just URLs. The reader decides how @@ -130,6 +132,9 @@ {partsList.length}p + @@ -263,6 +268,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/section/+page.svelte b/web/routes/uix/components/section/+page.svelte index 2b60f875a..40c21e6dd 100644 --- a/web/routes/uix/components/section/+page.svelte +++ b/web/routes/uix/components/section/+page.svelte @@ -3,8 +3,10 @@ import { Box } from '$uix/eidos/components/box'; import { compileMorfo } from '$uix/morfo'; import { sectionMorfo } from '@/uix/morfo/components/section'; + import TokensPanel from '../../lib/TokensPanel.svelte'; - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; type TraceEntry = { event: string; family: string; intent?: string; at: number }; let tab = $state('live'); let trace = $state([]); @@ -149,6 +151,9 @@ {events.length} + @@ -325,6 +330,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/split-button/+page.svelte b/web/routes/uix/components/split-button/+page.svelte index 67f4b7f1f..e0851a6f3 100644 --- a/web/routes/uix/components/split-button/+page.svelte +++ b/web/routes/uix/components/split-button/+page.svelte @@ -7,8 +7,10 @@ } from '$uix/eidos/components/split-button'; import { compileMorfo } from '$uix/morfo'; import { splitButtonMorfo } from '@/uix/morfo/components/split-button'; + import TokensPanel from '../../lib/TokensPanel.svelte'; - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; type TraceEntry = { event: string; family: string; intent?: string; at: number }; let tab = $state('live'); let trace = $state([]); @@ -193,6 +195,9 @@ + @@ -473,6 +478,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/sticky/+page.svelte b/web/routes/uix/components/sticky/+page.svelte index 47f7a1569..64f2d4043 100644 --- a/web/routes/uix/components/sticky/+page.svelte +++ b/web/routes/uix/components/sticky/+page.svelte @@ -8,11 +8,13 @@ import MotionPanel from '../../lib/MotionPanel.svelte'; import SemaPanel from '../../lib/SemaPanel.svelte'; import { DemoTrace } from '../../lib/harness.svelte'; + import TokensPanel from '../../lib/TokensPanel.svelte'; const uix = getActiveUix(); // prettier-ignore - type Tab = 'live' | 'system' | 'motion' | 'sema' | 'services' | 'api' | 'morfo' | 'recipe' | 'a11y'; + type Tab = 'live' | 'system' | 'motion' | 'sema' | 'services' | 'api' | 'morfo' | 'recipe' | 'tokens' + | 'a11y'; let tab = $state('live'); // ── Stage + System axes ────────────────────────────────────────────── @@ -192,6 +194,9 @@ + @@ -397,6 +402,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/time-range-field/+page.svelte b/web/routes/uix/components/time-range-field/+page.svelte index 2ebf20964..f50af4c18 100644 --- a/web/routes/uix/components/time-range-field/+page.svelte +++ b/web/routes/uix/components/time-range-field/+page.svelte @@ -8,6 +8,7 @@ import { compileMorfo } from '$uix/morfo'; import { timeRangeFieldMorfo } from '@/uix/morfo/components/time-range-field'; import { getActiveUix } from '$active-uix'; + import TokensPanel from '../../lib/TokensPanel.svelte'; import { Time, type TimeValue, @@ -16,7 +17,8 @@ type HourCycle } from '$libs/days'; - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; type TraceEntry = { event: string; family: string; intent?: string; at: number }; type Direction = 'ltr' | 'rtl'; @@ -239,6 +241,9 @@ {events.length} + @@ -488,6 +493,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/toggle-group/+page.svelte b/web/routes/uix/components/toggle-group/+page.svelte index c93f2e2e7..bb0df16b6 100644 --- a/web/routes/uix/components/toggle-group/+page.svelte +++ b/web/routes/uix/components/toggle-group/+page.svelte @@ -12,11 +12,13 @@ import { getActiveUix } from '$active-uix'; import { page } from '$app/state'; import { colorValue, PALETTE_SCALES } from '../../lib/harness.svelte'; + import TokensPanel from '../../lib/TokensPanel.svelte'; const uix = getActiveUix(); const params = page.url.searchParams; - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; let tab = $state('live'); // ── Live state ────────────────────────────────────────────────── @@ -234,6 +236,9 @@ {events.length} + @@ -707,6 +712,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe

diff --git a/web/routes/uix/components/tooltip/+page.svelte b/web/routes/uix/components/tooltip/+page.svelte index d5810e897..cb9021781 100644 --- a/web/routes/uix/components/tooltip/+page.svelte +++ b/web/routes/uix/components/tooltip/+page.svelte @@ -5,12 +5,14 @@ import { getActiveUix } from '$active-uix'; import type { Side, Align } from '$soma/layers/floating'; import { page } from '$app/state'; + import TokensPanel from '../../lib/TokensPanel.svelte'; const uix = getActiveUix(); const params = page.url.searchParams; - type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'a11y'; + type Tab = 'live' | 'api' | 'morfo' | 'sema' | 'recipe' | 'tokens' + | 'a11y'; type TraceEntry = { event: string; family: string; intent?: string; at: number }; let tab = $state('live'); let trace = $state([]); @@ -272,6 +274,9 @@ + @@ -901,6 +906,10 @@
{/if} + {#if tab === 'tokens'} + + {/if} + {#if tab === 'recipe'}

Eidos recipe