uix(fab): temable — 88 % → 100 %, y el modo va DETRÁS, no delante

Le faltaban DOS knobs y los dos son del pill extendido: el FAB circular no
declara ni `padding-inline` ni `gap`, pero la regla
`[data-button][data-fab][data-extended]` sí, y leía `var(--space-5)` /
`var(--space-2)` A PELO. La COSTURA del PLAN §2-A: el valor sigue siendo del
sistema, el knob pasa a ser del componente. `global` a CERO.

Claves que entran (2, defaults verbatim):

- `--fab-padding-inline-extended: var(--space-5)`
- `--fab-gap-extended: var(--space-2)`

El nombre lleva el cualificador DETRÁS. `extended` es un MODO del FAB, no un
estado interactivo (el vocabulario cerrado es hover · active · selected ·
disabled · checked · open · focus · invalid · current), así que cae en la otra
mitad de la frase firmada en D-TH.6 —«delante lo interactivo, detrás lo
dimensional y contextual»—, igual que `sidebar.width-icon` y
`radio-group.gap-vertical`. Un `--fab-padding-inline` a secas habría prometido
a TODO FAB un padding que sólo tiene el pill.

Lo que NO se acuña, y por qué el 100 % no lleva las tres claves de la §4:
el `font-size: 1em` del glifo es identidad de contexto y ya lleva su anotación
`/* literal: */` (fuera del ratio por recipe-contract §3), y la colocación
flotante es de la capa `viewport-placement`, cuya ranura de override Fab
escribe sin acuñar vocabulario paralelo (`--fab-offset` / `--fab-z` se
retiraron por eso en 2026-08-15).

La composición NO le quita nada, y valía la pena medirlo: el mismo `<button>`
lleva `data-button` Y `data-fab`, la forma exacta del hallazgo de
`gradient-picker` (36 claves muertas bajo `popover.css`). Aquí no ocurre por
construcción — las reglas dimensionales del FAB casan
`[data-button][data-fab][data-fab-size]` (0,3,0) contra los (0,2,0) de
`[data-button][data-size]`, así que ganan sea cual sea el orden de carga de los
chunks. Medido: padding computado 20px = `--space-5`, no el del Button.
Tampoco lleva `data-depth`, así que §12.9 no le aplica.

Censo: 16 knobs · público 14 → 16 · global 2 → 0 · excepción 1 (fuera del
ratio) · 88 % → 100 %. Contrato 10 → 12 claves.

Diff de computed: VACÍO en las dos formas. 416 valores × 7 estados en el
escenario por defecto (circular, sonda estándar) y 188 valores × 4 tallas +
hover en el pill extendido, con una sonda de un solo uso porque la demo
arranca circular. Capturas 2× antes/después byte a byte IDÉNTICAS en las dos.
No se tocó ninguna regla `:hover`, así que el paso 12 no aplica.

Centinela R-5.4: **11/12**, 1 adjudicada. `lift` es la laguna del INSTRUMENTO,
no del token: la receta lo consume con la propiedad `translate` (no
`transform`, para no pisar el press-squeeze del Button) dentro de una regla
`:hover`, y el guard ni fotografía `translate` —la misma laguna ya adjudicada
tres veces sobre `transform` en background / rating-group / card— ni pasa el
ratón en su pasada estática. Medido a mano con puntero real: `--fab-lift:
1234px` escrito ANTES de entrar da `translate: 0px -1234px` a los 300 ms →
alcanza. Y trae una trampa nueva: el centinela SE AUTO-CANCELA — un lift de ese
tamaño se lleva el nodo de debajo del cursor, `:hover` cae y el valor vuelve a
`none` hacia t+900 ms. Añadirle una pasada de hover al guard no lo mediría.

El instrumento aprendió dos cosas de este componente, las dos por el §2
«cuenta los nodos»: un FAB es UN nodo, así que su segunda superficie pintada
—el hueco de icono del Button compuesto— entra por `EXTRA_NODES` (1 → 2
nodos); y su eje de talla es `data-fab-size`, NO `data-size`, así que el
barrido genérico del guard no sellaba nada. Con el barrido cartesiano
`data-fab-size` × `data-extended` el guard pasa de **3/12 a 11/12** sin
adjudicar una sola clave de más. Los dos interruptores son entradas por
componente: no tocan a nadie más y no exigen re-verificar el ledger.

Guards: censo `--only fab` 100 % (global 68 %, no baja) · `--names` 12
conformes, 0 desviadas · `component-audit --only fab` PASS · `eidos-lint fab`
0 invalid (14 eidos-only) · `vitest run src/uix/eidos` 35/36 ficheros, el único
rojo es el conocido `skin-media-player` en `lint.test.ts` · `rtl:check` 0 ·
`docs:check` 0 · `npm run check` COMPLETED, cero errores en los ficheros
tocados (los 72 globales son de otras sesiones) · prettier limpio sobre el
contenido normalizado a LF.

README con su sección «Talla y tema» (tabla derivada del contrato), pestaña
`Tokens` en la demo verificada en navegador (12 claves, cero errores de
página) y veredicto §5 escrito en la ficha.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
alpha-0.1-background
dev 2 months ago
parent 1621de93c4
commit 5fd2fcdd86

@ -5,19 +5,16 @@
> Vista de conjunto: [README](./README.md) · método y protocolo: > Vista de conjunto: [README](./README.md) · método y protocolo:
> [`PLAN-theming.md`](../../process/PLAN-theming.md) §1, §2, §7. > [`PLAN-theming.md`](../../process/PLAN-theming.md) §1, §2, §7.
- **Medido**: 2026-08-23 · **Alcance**: **88%** — 14 de 16 knobs por token público - **Medido**: 2026-08-24 · **Alcance**: **100%** — 16 de 16 knobs por token público
- **Knobs de apariencia**: 16 — público 14 · privado 0 · global 2 · literal 0 · sistema 0 · excepción 1 _(los dos últimos, fuera del ratio)_ - **Knobs de apariencia**: 16 — público 16 · privado 0 · global 0 · literal 0 · sistema 0 · excepción 1 _(los dos últimos, fuera del ratio)_
- **Contrato hoy** (`lib/recipes/base.ts`): 10 pública(s) — `size-xs`, `size-sm`, `size-md`, `size-lg`, `icon-xs`, `icon-sm`, `icon-md`, `icon-lg`, `shadow`, `lift` - **Contrato hoy** (`lib/recipes/base.ts`): 12 pública(s) — `size-xs`, `size-sm`, `size-md`, `size-lg`, `icon-xs`, `icon-sm`, `icon-md`, `icon-lg`, `shadow`, `lift`, `padding-inline-extended`, `gap-extended`
- **Eje `size`**: no · **ficheros**: `fab.css` - **Eje `size`**: no · **ficheros**: `fab.css`
## 1. Knobs fuera de alcance ## 1. Knobs fuera de alcance
### 1.1 Directo a primitivo global (2) ### 1.1 Directo a primitivo global (0)
| # | fichero:línea | selector | propiedad | valor | _Ninguno._
| ---: | --- | --- | --- | --- |
| 1 | `fab.css:98` | `[data-button][data-fab][data-extended]` | `padding-inline` | `var(--space-5)` |
| 2 | `fab.css:99` | `[data-button][data-fab][data-extended]` | `gap` | `var(--space-2)` |
### 1.2 A través de un privado (0) ### 1.2 A través de un privado (0)
@ -52,7 +49,7 @@ _La receta no declara privados propios en su CSS._
- **Consume la capa compartida `list-surface`.** Un eje que la capa posee se consume como `var(--_x, var(--x))`; el consumidor **no acuña** `--fab-{eje}` para él — sería un vocabulario paralelo (README de `eidos/components`, «Capas compartidas» regla 2). - **Consume la capa compartida `list-surface`.** Un eje que la capa posee se consume como `var(--_x, var(--x))`; el consumidor **no acuña** `--fab-{eje}` para él — sería un vocabulario paralelo (README de `eidos/components`, «Capas compartidas» regla 2).
- **Consume la capa compartida `viewport-placement`.** Un eje que la capa posee se consume como `var(--_x, var(--x))`; el consumidor **no acuña** `--fab-{eje}` para él — sería un vocabulario paralelo (README de `eidos/components`, «Capas compartidas» regla 2). - **Consume la capa compartida `viewport-placement`.** Un eje que la capa posee se consume como `var(--_x, var(--x))`; el consumidor **no acuña** `--fab-{eje}` para él — sería un vocabulario paralelo (README de `eidos/components`, «Capas compartidas» regla 2).
### 4.1 Tokens a declarar en `lib/recipes/base.ts` (3) ### 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 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 puede moverlo. Nombres derivados de recipe-contract §1 (ejes lógicos, talla
@ -62,8 +59,6 @@ no distingue lo que debería — se marca `⚠`.
| token (`--fab-…`) | scope TSC | valor propuesto | usos | | token (`--fab-…`) | scope TSC | valor propuesto | usos |
| --- | --- | --- | ---: | | --- | --- | --- | ---: |
| `padding-inline` | `root` | `var(--space-5)` | 1 |
| `gap` | `root` | `var(--space-2)` | 1 |
| `font-size` | `root` | `1em` | 1 | | `font-size` | `root` | `1em` | 1 |
### 4.4 Lo que hay que comprobar a mano (PLAN-theming §1.3 · §7.4) ### 4.4 Lo que hay que comprobar a mano (PLAN-theming §1.3 · §7.4)
@ -78,6 +73,70 @@ no distingue lo que debería — se marca `⚠`.
<!-- veredicto:start --> <!-- veredicto:start -->
_(pendiente — lo escribe el autor; se conserva al regenerar)_ **Medido y CERRADO al 100 % el 2026-08-24** (88 % → 100 %, 10 → 12 claves de
contrato, centinela **11/12** con 1 adjudicada).
**Lo que faltaba eran DOS knobs, y los dos del pill extendido.** El FAB
circular no declara ni `padding-inline` ni `gap`; la regla
`[data-button][data-fab][data-extended]` sí, y leía `var(--space-5)` /
`var(--space-2)` A PELO. Es la COSTURA del PLAN §2-A: el valor sigue siendo del
sistema, el knob pasa a ser del componente —
`--fab-padding-inline-extended` / `--fab-gap-extended`, defaults verbatim.
`global` a CERO.
**El nombre**: el cualificador va DETRÁS. `extended` es un MODO del FAB, no un
estado interactivo (el vocabulario cerrado es hover · active · selected ·
disabled · checked · open · focus · invalid · current), así que cae en la otra
mitad de la frase firmada en D-TH.6 — «detrás lo dimensional y contextual»,
igual que `sidebar.width-icon` y `radio-group.gap-vertical`. Y un
`--fab-padding-inline` a secas MENTIRÍA: prometería a todo FAB un padding que
sólo tiene el pill.
**Lo que NO se acuña**, y por qué el 100 % no lleva las tres claves que
proponía la §4:
- El `font-size: 1em` del glifo es **identidad de contexto** y ya lleva su
anotación `/* literal: */` — fuera del ratio por la válvula de
recipe-contract §3.
- La colocación flotante es de la capa compartida `viewport-placement`. Fab
escribe su **ranura de override** (`--_viewport-placement-z`) y no acuña
vocabulario paralelo: `--fab-offset` y `--fab-z` ya se retiraron por eso
(2026-08-15).
**La composición NO le quita nada.** El aviso valía la pena comprobarlo: el
mismo `<button>` lleva `data-button` **y** `data-fab`, que es la forma exacta
del hallazgo de `gradient-picker` (36 claves muertas bajo `popover.css`). Aquí
no ocurre, y por construcción: las reglas dimensionales del FAB casan
`[data-button][data-fab][data-fab-size]` (0,3,0) contra los (0,2,0) de
`[data-button][data-size]`, así que ganan sea cual sea el orden de carga de los
chunks — lo que su propia cabecera de receta ya declaraba, ahora medido
(padding computado 20 px = `--space-5`, no el del Button). Tampoco lleva
`data-depth`, así que §12.9 no le aplica.
**Lo que el instrumento no ve** — `lift`, la única adjudicada. La receta lo
consume con la propiedad **`translate`** (no `transform`, para no pisar el
press-squeeze del Button) dentro de una regla `:hover`. El guard ni fotografía
`translate` — la misma laguna ya adjudicada tres veces sobre `transform`
(background, rating-group, card) — ni pasa el ratón en su pasada estática.
Medido a mano con puntero real: `--fab-lift: 1234px` escrito ANTES de entrar
da `translate: 0px -1234px` a los 300 ms → **alcanza**. Y trae una trampa
nueva que conviene tener escrita: **el propio centinela se auto-cancela**, un
lift de ese tamaño se lleva el nodo de debajo del cursor, `:hover` cae y el
valor vuelve a `none` hacia t+900 ms. Añadirle una pasada de hover al guard NO
lo mediría.
**Diff de computed = 0** en las dos formas: 416 valores × 7 estados en el
escenario por defecto (circular) y 188 valores × 4 tallas + hover en el pill
extendido, medido con una sonda de un solo uso porque la demo arranca
circular. Capturas 2× antes/después **byte a byte idénticas** en las dos
formas.
**El instrumento aprendió dos cosas de este componente**: un FAB es UN nodo
(la sonda medía 1 — la bandera de «cuenta los nodos»), así que su segunda
superficie pintada, el hueco de icono del Button compuesto, entra por
`EXTRA_NODES`; y su eje de talla es `data-fab-size`, **no** `data-size`, así
que el barrido genérico del guard no sellaba nada y los seis pasos xs/sm/lg
leían muertos. Con el barrido cartesiano de `data-fab-size` × `data-extended`
el guard pasa de **3/12 a 11/12** sin adjudicar una sola clave de más.
<!-- veredicto:end --> <!-- veredicto:end -->

@ -99,7 +99,13 @@ const EXTRA_NODES: Record<string, string> = {
'[data-chat-log] [data-virtual-list-viewport], [data-chat-log-to-latest] svg, [data-chat-log-separator-day] > *', '[data-chat-log] [data-virtual-list-viewport], [data-chat-log-to-latest] svg, [data-chat-log-separator-day] > *',
// Both glyphs are bare `<svg>` children of the parts that carry the attrs, // Both glyphs are bare `<svg>` children of the parts that carry the attrs,
// and the recipe sizes them by descendant selector. // and the recipe sizes them by descendant selector.
'chat-composer': '[data-chat-composer-send] > svg, [data-chat-composer-context-close] > svg' 'chat-composer': '[data-chat-composer-send] > svg, [data-chat-composer-context-close] > svg',
// A FAB is ONE node (the composed `<button>` carrying `data-fab`), so the
// attribute filter saw a single node — the "count the nodes" flag. Its second
// painted surface is the composed Button's icon slot, which the recipe sizes
// by descendant selector (`[data-fab] [data-button-icon]`) and which carries
// the Button's attr, not the FAB's.
fab: '[data-fab] [data-button-icon]'
}; };
/** /**

@ -21,6 +21,16 @@ 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)'; '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>> = { export const SENTINEL_EXCEPTIONS: Record<string, Record<string, string>> = {
fab: {
// 2026-08-24. ONE key, and it is the guard's blind spot for `translate` —
// the same limit already adjudicated for `transform` on background,
// rating-group and card, on the sibling property. Three independent
// reasons, all measured: the property is not in the read set; the static
// pass parks the pointer and this rule is `:hover`-only; and a sentinel-
// sized lift moves the node OUT from under the cursor, so the state
// cancels itself (`:hover` true at t+50ms, false by t+300ms).
lift: 'the guard does not snapshot `translate` (the `transform` limit of background / rating-group / card on the sibling property) and its static pass never hovers, while this rule is `[data-fab]:hover:not([data-disabled]):not(:active)`. Measured by hand with a real pointer: set --fab-lift=1234px BEFORE hovering and the FAB computes `translate: 0px -1234px` at t+300ms -> reaches. Note the self-cancel that makes it unmeasurable even with a hover pass: a 1234px lift carries the node out from under the cursor, :hover drops and it settles back to none by t+900ms'
},
avatar: { avatar: {
// 2026-08-23. Five steps of scales the measured stage does not wear, all // 2026-08-23. Five steps of scales the measured stage does not wear, all
// forced on the REAL nodes with transitions frozen. Two of them sit on the // forced on the REAL nodes with transitions frozen. Two of them sit on the

@ -248,6 +248,23 @@ const COMPONENT_OVERRIDES: Record<
// (an `<a>`) navigates instead of revealing the panel, so the portaled // (an `<a>`) navigates instead of revealing the panel, so the portaled
// content never enters the document and 32 of its 35 tokens read dead. // content never enters the document and 32 of its 35 tokens read dead.
'link-preview': { openBy: 'hover' }, 'link-preview': { openBy: 'hover' },
// Two axes, and the guard knew NEITHER of them (3/12 without this entry).
// (1) The FAB's size axis is `data-fab-size`, not `data-size` — it is an
// eidos-only visual attr with its own scale off the control ladder, so the
// generic size sweep stamped nothing and the six xs/sm/lg steps read dead.
// (2) Its EXTENDED pill is a boolean mode whose absence is the default: the
// demo boots circular, so the two keys that only paint under
// `[data-extended]` had no node. Sweeping the two as a product measures the
// circular form AND the pill instead of trading one for the other.
fab: {
// A FAB is ONE node; its second painted surface is the composed Button's
// icon slot, sized by descendant selector and carrying Button's attr.
extraNodes: '[data-fab] [data-button-icon]',
sweepAttr: [
{ attr: 'data-fab-size', values: ['md', 'xs', 'sm', 'lg'] },
{ attr: 'data-extended', values: [null, ''] }
]
},
// A tooltip opens on POINTER-OVER too: clicking its trigger does nothing and // A tooltip opens on POINTER-OVER too: clicking its trigger does nothing and
// the panel never enters the document — 24 of its 24 tokens read dead // the panel never enters the document — 24 of its 24 tokens read dead
// (measured 2026-08-23). // (measured 2026-08-23).

@ -21,6 +21,43 @@ It floats over content (own `placement`, fixed) and lifts on hover.
</Fab> </Fab>
``` ```
## Talla y tema
**12 claves públicas** en `lib/recipes/base.ts`: la escala propia del FAB
—diámetro (`size-{xs…lg}`) y glifo (`icon-{xs…lg}`), deliberadamente FUERA de
la escalera `--control-height-*`— más la elevación (`shadow`), el `lift` del
hover y el ritmo del pill extendido (`padding-inline-extended`, `gap-extended`).
La pestaña **Tokens** de su demo las resuelve en vivo.
| eje | claves | valor por defecto |
| --- | --- | --- |
| diámetro | `size-xs` · `size-sm` · `size-md` · `size-lg` | `1.875rem` · `2.5rem` · `3.5rem` · `4.5rem` |
| glifo | `icon-xs` · `icon-sm` · `icon-md` · `icon-lg` | `1rem` · `1.25rem` · `1.5rem` · `1.75rem` |
| elevación | `shadow` · `lift` | `var(--shadow-overlay)` · `2px` |
| pill extendido | `padding-inline-extended` · `gap-extended` | `var(--space-5)` · `var(--space-2)` |
Lo que entró el **2026-08-24** (88 % → 100 %): las **dos** del pill extendido,
que leían `var(--space-5)` y `var(--space-2)` a pelo desde el CSS — la COSTURA
del PLAN §2-A: el valor es del sistema, el knob es del componente. El
cualificador va DETRÁS (`padding-inline-extended`, no
`extended-padding-inline`) porque `extended` es un MODO, no un estado
interactivo — la misma forma que `sidebar.width-icon` (D-TH.6). Un
`padding-inline` a secas habría prometido a TODO FAB un padding que sólo tiene
el pill: el FAB circular no declara ninguno de los dos.
**Lo que no se acuña**: el `font-size: 1em` del glifo es identidad de contexto
(lleva su anotación `/* literal: */` y sale del ratio), y la colocación
flotante es de la capa `viewport-placement` — Fab escribe su ranura de
override, no acuña vocabulario paralelo (ver «Decisiones»).
**Lo que el guard da por silencioso**: `lift`, y por el instrumento, no por el
token. La receta lo consume con la propiedad `translate` en una regla
`:hover`, y el guard ni fotografía `translate` ni pasa el ratón en su pasada
estática. Medido a mano con un puntero real: `--fab-lift: 1234px` escrito
ANTES de entrar da `translate: 0px -1234px` a los 300 ms. Ojo al auto-cancelado
que lo hace inmedible incluso con pasada de hover: un lift de ese tamaño se
lleva el nodo de debajo del cursor, `:hover` cae y vuelve a `none`.
## Baseline ## Baseline
No Air baseline (the old `air/layout/float` was a generic 3×3 placement util, No Air baseline (the old `air/layout/float` was a generic 3×3 placement util,

@ -95,8 +95,8 @@
* inline padding + a gap between the icon and the label. */ * inline padding + a gap between the icon and the label. */
[data-button][data-fab][data-extended] { [data-button][data-fab][data-extended] {
inline-size: auto; inline-size: auto;
padding-inline: var(--space-5); padding-inline: var(--fab-padding-inline-extended);
gap: var(--space-2); gap: var(--fab-gap-extended);
} }
/* The visible glyph follows the FAB's font-size (1em icon). */ /* The visible glyph follows the FAB's font-size (1em icon). */

@ -4884,6 +4884,8 @@
--fab-icon-lg: 1.75rem; --fab-icon-lg: 1.75rem;
--fab-shadow: var(--shadow-overlay); --fab-shadow: var(--shadow-overlay);
--fab-lift: 2px; --fab-lift: 2px;
--fab-padding-inline-extended: var(--space-5);
--fab-gap-extended: var(--space-2);
--onion-menu-trigger-lift: var(--fab-lift); --onion-menu-trigger-lift: var(--fab-lift);
--onion-menu-trigger-shadow: var(--fab-shadow); --onion-menu-trigger-shadow: var(--fab-shadow);
--onion-menu-trigger-radius: var(--radius-full); --onion-menu-trigger-radius: var(--radius-full);

@ -8440,7 +8440,15 @@ export const THEME_BASE_RECIPE_TOKENS = defineRecipes({
// bridge. Minting `--fab-offset` / `--fab-z` only created a parallel // bridge. Minting `--fab-offset` / `--fab-z` only created a parallel
// vocabulary whose sole reader was the bridge translating it back. // vocabulary whose sole reader was the bridge translating it back.
shadow: 'var(--shadow-overlay)', shadow: 'var(--shadow-overlay)',
lift: '2px' lift: '2px',
// The EXTENDED pill's own inline rhythm. The qualifier rides BEHIND
// (D-TH.6: «delante lo interactivo, detrás lo dimensional y contextual» —
// same shape as `sidebar.width-icon` and `radio-group.gap-vertical`):
// `extended` is a MODE of the FAB, not a state of the control, and the
// circular form has neither of the two — a bare `padding-inline` would
// promise every FAB a padding only the pill has.
'padding-inline-extended': 'var(--space-5)',
'gap-extended': 'var(--space-2)'
}, },
// ───────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────

@ -4,8 +4,9 @@
import { compileMorfo } from '$uix/morfo'; import { compileMorfo } from '$uix/morfo';
import { fabMorfo } from '@/uix/morfo/components/fab'; import { fabMorfo } from '@/uix/morfo/components/fab';
import type { ButtonVariant } from '$uix/eidos/components/button'; import type { ButtonVariant } from '$uix/eidos/components/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 }; type TraceEntry = { event: string; family: string; intent?: string; at: number };
let tab = $state<Tab>('live'); let tab = $state<Tab>('live');
let trace = $state<TraceEntry[]>([]); let trace = $state<TraceEntry[]>([]);
@ -184,6 +185,9 @@
</button> </button>
<button data-uix-tab data-active={tab === 'recipe'} onclick={() => (tab = 'recipe')}>Recipe</button <button data-uix-tab data-active={tab === 'recipe'} onclick={() => (tab = 'recipe')}>Recipe</button
> >
<button data-uix-tab data-active={tab === 'tokens'} onclick={() => (tab = 'tokens')}>
Tokens <span data-uix-tab-count>12</span>
</button>
<button data-uix-tab data-active={tab === 'a11y'} onclick={() => (tab = 'a11y')}>A11y</button> <button data-uix-tab data-active={tab === 'a11y'} onclick={() => (tab = 'a11y')}>A11y</button>
</div> </div>
@ -377,6 +381,10 @@
</section> </section>
{/if} {/if}
{#if tab === 'tokens'}
<TokensPanel component="fab" stage={stageRef ?? undefined} />
{/if}
{#if tab === 'recipe'} {#if tab === 'recipe'}
<section data-uix-section> <section data-uix-section>
<h2 data-uix-section-title>Eidos recipe</h2> <h2 data-uix-section-title>Eidos recipe</h2>

Loading…
Cancel
Save

Powered by TurnKey Linux.