# Pendientes UIX
> Backlog vivo. Cada entrada lleva una disposición: **implementar** /
> **diferir** / **descartar**. Mantener priorizado por capa afectada y
> dependencias.
## Pickers — estado consolidado 2026-05-21
El bloque de trabajo sobre `date-picker` y `date-range-picker` cerró en
una pasada larga el mismo día. El contrato canónico es:
- **`mode: 'inline' | 'modal'`** — modal bloquea outside-click + Escape.
- **`kind: 'date' | 'month' | 'year'`** (Chakra-style) — controla
segments del input + view del popover. Derivación vive en el
`DateFieldProvider` (soma), no en el snippet del consumer.
- **Footer = composición pura** — `<Picker.Footer>` contiene las parts
que tú compongas (`< Clear /> `, `<Cancel/>` , `<Close/>` ). Sin
`clearButton` /`cancelButton`/`closeButton` props en root.
- **Provider helpers**: `commit()` / `cancel()` (revierte al snapshot
capturado en el OPEN edge vía `watch(open)` ) / `clear()` .
| Item | Disposición |
| --- | --- |
| Aplicar `mode + Footer` a `date-picker` (single) | **hecho** |
| Aplicar `kind` (Chakra date/month/year) a `date-picker` | **hecho** |
| `<DatePicker.YearView>` + `<DatePicker.MonthView>` | **hecho** |
| Propagar `kind` a `date-range-picker` (ambos endpoints filtran segments) | **hecho** |
| `<DateRangePicker.YearView>` + `<DateRangePicker.MonthView>` (range state machine: start → end → reset, swap automático) | **hecho** |
| Promover `Footer/Clear/Cancel/Close` a parts canónicos Eidos (ambos pickers) | **hecho** |
| Drop `clearButton/cancelButton/closeButton` root props → composición pura | **hecho** |
| Morfo `date-picker` + `date-range-picker` : declarar parts Footer/Clear/Cancel/Close + arquetipo `footer` añadido al vocabulario | **hecho** |
| `MonthRangePicker` / `YearRangePicker` como componentes nuevos | **descartar** — cubierto por `<DateRangePicker kind='month'>` / `kind='year'` . No vale la pena duplicar superficie cuando un prop captura la variante. |
| `MonthPicker` / `YearPicker` (single) | **descartar** — idem, `<DatePicker kind='month'>` / `kind='year'` . |
| Promover `<DatePicker.YearView>` / `<DatePicker.MonthView>` a componentes independientes `<YearCalendar>` / `<MonthCalendar>` con demos aislados | **diferir** — actualmente acoplados al `DatePickerProvider` . Independizarlos requiere refactor del context-lookup. Mantener acoplados hasta que aparezca un caso de uso real fuera del picker. |
| Propagar el patrón modal+Footer a `time-picker` , `time-range-picker` , `color-picker` , `combobox` , `select` , `popover` cuando proceda | **implementar** — decidir por componente; muchos no necesitan footer. |
| Tests browser del flujo completo (Playwright): inline/modal, kind chip, range state machine, snapshot/cancel, click-outside, Escape | **implementar** — alta cobertura para flujos que ahora dependen de state machine. |
| Sema event al bloquear click cuando `mode='modal'` | **diferir** — útil para screen reader feedback. No bloquea. |
## Soma / Popover — bloqueo detectado durante Words
| Item | Disposición |
| --- | --- |
| Auditar `Popover` como componente propio antes de usarlo para `Words.ToolPopover` | **implementar** — el trigger emite `present` en la traza, pero el estado `open` no queda reflejado de forma fiable en DOM y `Content` puede no montarse. En la demo de `Words` , abrir el editor de link desde el `BubbleMenu` produce `TypeError: Cannot read properties of undefined (reading 'wrapperProps')` en `src/uix/soma/components/popover/popover-provider.svelte.ts` . No es una adaptación específica de `Words` ; es deuda de `Soma/Popover` y debe resolverse con su propia demo, tests y audit visual. |
| Revisar `Portal` sólo si la auditoría de `Popover` lo confirma | **diferir** — no modificar `internal/Portal` como efecto lateral de `Words` ; aislar primero si el fallo está en trigger/provider/presence/portal. |
| Añadir test browser o harness Svelte para click real de `Popover.Trigger` → `Content` visible | **implementar** — los tests unitarios del provider no cubren el flujo renderizado con `Trigger` , `Portal` , `Content` , `bind:open` y atributos morfo en DOM. |
## Tooltip (warnings pendientes del audit)
| Item | Disposición |
| --- | --- |
| `A-3.6` evento `open` /`close` sin variante `{verb}-X` o `{family}-X` | **diferir** — disclosure puro, el naming actual es semánticamente válido. |
| `D-4.3` demo no emite `uix.events.emit(...)` para wirear Play buttons | **implementar** cuando se haga la próxima pasada de demos. |
eidos: theming fixes + size/variant parity batch + docs
- theme: add surface.muted + content.muted to color contract (neutral-3
+ neutral-10). Plugs 17 broken --color-content-muted and 3 broken
--color-surface-muted references in recipes/components.
- form.css: fix --color-neutral-element-hover typo → --color-neutral-hover.
- archetypes.css + events.css: replace raw hsl/rgba indigo with
color-mix(var(--color-primary-solid) …) — no raw colors left in eidos.
- combobox dark scrollbar: unscope ::-webkit-scrollbar rules in uix.css
and duplicate --uix-line on :root + :root[data-mode='dark'] so portaled
overlays (Combobox listbox, Popover, Dialog, Drawer) inherit the theme.
- sizes: 20 components expand from sm/md/lg to xs..xl (form controls,
text inputs, progress/meter, field/form) or xs..lg (nav controls:
breadcrumb, pagination, tag-group, toolbar). Composite panels keep
sm/md/lg deliberately.
- variants: field + toolbar drop arbitrary ControlVariant narrowings;
both expose all 3 (surface | outline | ghost) with new outline CSS.
- pagination demo: disambiguate siblingCount/boundaryCount as "per side"
in label + API table (Radix/MUI convention).
- docs: CHECKLIST §C-2.6 (contract token presence) + §D-7.4 (chip parity)
+ §D-7.5 (size category) added. DEMO_AUTHORING §12.7 (chip parity) +
§12.8 (size category cheatsheet) added. eidos/README +
active_architecture.md sync texts/migration nomenclature.
- PENDIENTES.md: normas N-1..N-5 implantadas en esta sesión.
Verification: 88/88 eidos tests, 0 type errors, 67/67 component:audit PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
## Eidos theming — limpieza diferida
| Item | Disposición |
| --- | --- |
| 20 tokens de color muertos (rol `tertiary` completo + `{intent}-active` × 8 + `fulfill-hover` /`loss-hover`/`loss-element`) en `themes/base.ts` + `generated/base.css` | **diferir** — no rompen nada. Validar que `tertiary` no es un hook futuro reservado antes de borrarlo. |
| Afinar valores de los tokens xs/xl extrapolados durante el batch de tamaños | **diferir** — la extrapolación proporcional (xs ≈ 75% de sm, xl ≈ 125% de lg) puede no proporcionarse bien en componentes concretos; revisar visualmente y reajustar caso por caso. |
| Range view-cell: differentiate visualmente start/end vs in-range (actualmente todos se ven solid primary) — pendiente afinar tinte de `data-in-range` para que sea más sutil que start/end | **implementar** cuando se haga el browser-walk del range-picker. |
eidos: theming fixes + size/variant parity batch + docs
- theme: add surface.muted + content.muted to color contract (neutral-3
+ neutral-10). Plugs 17 broken --color-content-muted and 3 broken
--color-surface-muted references in recipes/components.
- form.css: fix --color-neutral-element-hover typo → --color-neutral-hover.
- archetypes.css + events.css: replace raw hsl/rgba indigo with
color-mix(var(--color-primary-solid) …) — no raw colors left in eidos.
- combobox dark scrollbar: unscope ::-webkit-scrollbar rules in uix.css
and duplicate --uix-line on :root + :root[data-mode='dark'] so portaled
overlays (Combobox listbox, Popover, Dialog, Drawer) inherit the theme.
- sizes: 20 components expand from sm/md/lg to xs..xl (form controls,
text inputs, progress/meter, field/form) or xs..lg (nav controls:
breadcrumb, pagination, tag-group, toolbar). Composite panels keep
sm/md/lg deliberately.
- variants: field + toolbar drop arbitrary ControlVariant narrowings;
both expose all 3 (surface | outline | ghost) with new outline CSS.
- pagination demo: disambiguate siblingCount/boundaryCount as "per side"
in label + API table (Radix/MUI convention).
- docs: CHECKLIST §C-2.6 (contract token presence) + §D-7.4 (chip parity)
+ §D-7.5 (size category) added. DEMO_AUTHORING §12.7 (chip parity) +
§12.8 (size category cheatsheet) added. eidos/README +
active_architecture.md sync texts/migration nomenclature.
- PENDIENTES.md: normas N-1..N-5 implantadas en esta sesión.
Verification: 88/88 eidos tests, 0 type errors, 67/67 component:audit PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
## Audit one-by-one (post-sesión)
### Prioridad media
- [ ] dialog (verificar visual)
eidos: theming fixes + size/variant parity batch + docs
- theme: add surface.muted + content.muted to color contract (neutral-3
+ neutral-10). Plugs 17 broken --color-content-muted and 3 broken
--color-surface-muted references in recipes/components.
- form.css: fix --color-neutral-element-hover typo → --color-neutral-hover.
- archetypes.css + events.css: replace raw hsl/rgba indigo with
color-mix(var(--color-primary-solid) …) — no raw colors left in eidos.
- combobox dark scrollbar: unscope ::-webkit-scrollbar rules in uix.css
and duplicate --uix-line on :root + :root[data-mode='dark'] so portaled
overlays (Combobox listbox, Popover, Dialog, Drawer) inherit the theme.
- sizes: 20 components expand from sm/md/lg to xs..xl (form controls,
text inputs, progress/meter, field/form) or xs..lg (nav controls:
breadcrumb, pagination, tag-group, toolbar). Composite panels keep
sm/md/lg deliberately.
- variants: field + toolbar drop arbitrary ControlVariant narrowings;
both expose all 3 (surface | outline | ghost) with new outline CSS.
- pagination demo: disambiguate siblingCount/boundaryCount as "per side"
in label + API table (Radix/MUI convention).
- docs: CHECKLIST §C-2.6 (contract token presence) + §D-7.4 (chip parity)
+ §D-7.5 (size category) added. DEMO_AUTHORING §12.7 (chip parity) +
§12.8 (size category cheatsheet) added. eidos/README +
active_architecture.md sync texts/migration nomenclature.
- PENDIENTES.md: normas N-1..N-5 implantadas en esta sesión.
Verification: 88/88 eidos tests, 0 type errors, 67/67 component:audit PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### Prioridad baja — sólo si aparece síntoma visual
Lista barrida en el audit script (component:audit 67/67 PASS). Cuando
eidos: theming fixes + size/variant parity batch + docs
- theme: add surface.muted + content.muted to color contract (neutral-3
+ neutral-10). Plugs 17 broken --color-content-muted and 3 broken
--color-surface-muted references in recipes/components.
- form.css: fix --color-neutral-element-hover typo → --color-neutral-hover.
- archetypes.css + events.css: replace raw hsl/rgba indigo with
color-mix(var(--color-primary-solid) …) — no raw colors left in eidos.
- combobox dark scrollbar: unscope ::-webkit-scrollbar rules in uix.css
and duplicate --uix-line on :root + :root[data-mode='dark'] so portaled
overlays (Combobox listbox, Popover, Dialog, Drawer) inherit the theme.
- sizes: 20 components expand from sm/md/lg to xs..xl (form controls,
text inputs, progress/meter, field/form) or xs..lg (nav controls:
breadcrumb, pagination, tag-group, toolbar). Composite panels keep
sm/md/lg deliberately.
- variants: field + toolbar drop arbitrary ControlVariant narrowings;
both expose all 3 (surface | outline | ghost) with new outline CSS.
- pagination demo: disambiguate siblingCount/boundaryCount as "per side"
in label + API table (Radix/MUI convention).
- docs: CHECKLIST §C-2.6 (contract token presence) + §D-7.4 (chip parity)
+ §D-7.5 (size category) added. DEMO_AUTHORING §12.7 (chip parity) +
§12.8 (size category cheatsheet) added. eidos/README +
active_architecture.md sync texts/migration nomenclature.
- PENDIENTES.md: normas N-1..N-5 implantadas en esta sesión.
Verification: 88/88 eidos tests, 0 type errors, 67/67 component:audit PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
aparezca un disparate visual, se walka el componente con browser y se
remedia. No se hace barrido proactivo de nada que ya esté PASS.
## Audit infra
| Item | Disposición |
| --- | --- |
| Audit A-3.6 falla con eventos `open` /`close` válidos de `emerge` | **diferir** — el regex pide `{verb}-X` pero muchos verbs son legítimos solos. Refinar regex para aceptar verbs canónicos. |
| Audit no verifica que el demo cierre el popover al hacer click-outside (cuando aplica) | **diferir** — verificación visual queda al browser-walk. |
| Translations check: añadir warning cuando un componente declara `texts.label` pero su catálogo no tiene `label` | **implementar** — pequeño, evita drift. |
| **Audit R-2.6** — `var(--color-X)` referenciado sin estar declarado en `generated/base.css` | **hecho** (`scripts/component-audit.ts`). Set declarado se calcula al inicio desde `generated/base.css` ; cada componente CSS se chequea contra él. |
| **Audit D-7.4** — el array de chips de cada control (size, variant, color) enumera el tipo completo declarado en `types.ts` | **hecho** (`scripts/component-audit.ts`). Parsea `{PascalName}{Prop}` exacto, resuelve alias canónicos (`ControlVariant`, `SelectionVariant` , `ChipVariant` , `MarkerVariant` , `TabsVariant` , `ColorRole` +narrowings) vía `SHARED_VARIANT_VOCAB` . |
| Nuevo: audit que verifique que ninguna Part Eidos consulta `provider.opts.{boolean}Button.current` (composición pura) | **diferir** — chequeo defensivo, low value. |
## Web · performance del docs site
Diagnóstico (2026-05-24): el usuario reporta carga lenta + Chrome marca
`[Violation] 'setTimeout' handler took 78ms` . Profiling identifica 4
cuellos de botella reales, ordenados por impacto. Como UIX está en fase
de desarrollo del framework, todos quedan como **diferir** hasta entrar
en pasada de polish; documentados aquí para no perder el rastro.
| Item | Disposición |
| --- | --- |
| **CSS layout 744 KB render-blocking** : `src/uix/eidos/index.css` `@import` -ea 70+ recipes + `generated/base.css` (213 KB) — total 944 KB. Cada `/uix/*` descarga + parsea todo antes del first paint, la mayoría para componentes que la página no usa. | **diferir** — fix arquitectónico: dejar foundation global (~250 KB: `base.css` + `archetypes.css` + `events.css` ) y mover cada recipe `XComponent.css` a un `import` dentro del `.svelte` correspondiente para que Vite lo code-splittee con el JS. Esto requiere migrar la convención del foundation eidos. |
| ** `ActiveEidos.create({ applyDom: true })` re-genera todo en runtime**: `apply()` (`src/uix/eidos/active-eidos.svelte.ts:361-389`) corre `renderStaticCss()` + `renderThemeCss()` sincrónicamente, itera `THEME_BASE_RECIPE_TOKENS` (2.884 líneas) + color× scale× role× alpha (>1k declaraciones), inyecta 3 `<style>` tags con `textContent = css` . Es la causa más probable de la violación `setTimeout 78ms` (el `$effect` envolvente se programa vía la cola que Chrome reporta como setTimeout). Además **duplica** el CSS bundleado vía `import '@/uix/eidos/index.css'` . | **diferir + investigar trade-off** — fix conservador (1 línea): `applyDom: false` en `web/routes/uix/+layout@.svelte:302` y depender del CSS bundleado. Pero hay que confirmar primero si runtime theme switching depende de la inyección (theme editors live). Si depende, la solución es hacer `apply()` lazy: cachear el render por `themeId` y solo inyectar overrides cuando `setCssVariables()` se llame. |
| **28 sema modules + 71 lang files eagerly imported en el layout** : `web/routes/uix/+layout@.svelte:10-38` (sema) + `src/uix/langs/components/index.ts` (langs). Añade ~30 KB al chunk del layout, bloquea tree-shaking, cada `/uix/*` registra todos aunque el usuario no abra esos componentes. | **diferir** — fix arquitectónico: registración lazy por componente. Cada componente al montar registra su propio sema/langs pack en lugar de el central en boot. Requiere API nueva (`uix.events.registerPack`/`uix.langs.lazy`) + refactor del patrón de boot. |
| **Sidebar con 100+ links `data-sveltekit-preload-{code,data}="hover"`** : `web/routes/uix/+layout@.svelte:746-769` . Mover el cursor por el rail dispara fetches masivos. Las rutas docs son prerenderizadas — el `preload-data` no aporta nada. | **diferir** — fix barato (5 líneas): quitar `data-sveltekit-preload-data` de los links del rail; cambiar `data-sveltekit-preload-code="hover"` a `viewport` para que precargue al entrar en pantalla, no al hover. Mantener `hover` en topbar/brand. |
**Cuándo abordarlo**: cuando la lib entre en pasada de optimización
pre-release. El orden de ataque sugerido es el inverso del coste:
quitar `preload-data` del rail (10 minutos, ganancia inmediata) → fijar
`applyDom: false` con cache lazy (medio día, gana 50-80ms) → split CSS
por componente (1-2 días, gana el grueso del transfer) → sema/langs
lazy registration (sprint propio).
## Doc debt
| Item | Disposición |
| --- | --- |
| READMEs/architecture docs siguen citando `morfo.translations` en muchos `.md` | **diferir** — el código está migrado a `texts` , los docs lagging. Sweep separado. |
| `src/uix/COMPONENT_COMPLETION_CHECKLIST.md` actualizado con C-2.6 + D-7.4 + D-7.5 | **hecho** |
| `src/uix/eidos/README.md` + `web/routes/uix/lib/DEMO_AUTHORING_GUIDE.md` actualizados con N-6 (kind) + N-7 (composition) | **hecho** |
eidos: theming fixes + size/variant parity batch + docs
- theme: add surface.muted + content.muted to color contract (neutral-3
+ neutral-10). Plugs 17 broken --color-content-muted and 3 broken
--color-surface-muted references in recipes/components.
- form.css: fix --color-neutral-element-hover typo → --color-neutral-hover.
- archetypes.css + events.css: replace raw hsl/rgba indigo with
color-mix(var(--color-primary-solid) …) — no raw colors left in eidos.
- combobox dark scrollbar: unscope ::-webkit-scrollbar rules in uix.css
and duplicate --uix-line on :root + :root[data-mode='dark'] so portaled
overlays (Combobox listbox, Popover, Dialog, Drawer) inherit the theme.
- sizes: 20 components expand from sm/md/lg to xs..xl (form controls,
text inputs, progress/meter, field/form) or xs..lg (nav controls:
breadcrumb, pagination, tag-group, toolbar). Composite panels keep
sm/md/lg deliberately.
- variants: field + toolbar drop arbitrary ControlVariant narrowings;
both expose all 3 (surface | outline | ghost) with new outline CSS.
- pagination demo: disambiguate siblingCount/boundaryCount as "per side"
in label + API table (Radix/MUI convention).
- docs: CHECKLIST §C-2.6 (contract token presence) + §D-7.4 (chip parity)
+ §D-7.5 (size category) added. DEMO_AUTHORING §12.7 (chip parity) +
§12.8 (size category cheatsheet) added. eidos/README +
active_architecture.md sync texts/migration nomenclature.
- PENDIENTES.md: normas N-1..N-5 implantadas en esta sesión.
Verification: 88/88 eidos tests, 0 type errors, 67/67 component:audit PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
## Normas implantadas
eidos: theming fixes + size/variant parity batch + docs
- theme: add surface.muted + content.muted to color contract (neutral-3
+ neutral-10). Plugs 17 broken --color-content-muted and 3 broken
--color-surface-muted references in recipes/components.
- form.css: fix --color-neutral-element-hover typo → --color-neutral-hover.
- archetypes.css + events.css: replace raw hsl/rgba indigo with
color-mix(var(--color-primary-solid) …) — no raw colors left in eidos.
- combobox dark scrollbar: unscope ::-webkit-scrollbar rules in uix.css
and duplicate --uix-line on :root + :root[data-mode='dark'] so portaled
overlays (Combobox listbox, Popover, Dialog, Drawer) inherit the theme.
- sizes: 20 components expand from sm/md/lg to xs..xl (form controls,
text inputs, progress/meter, field/form) or xs..lg (nav controls:
breadcrumb, pagination, tag-group, toolbar). Composite panels keep
sm/md/lg deliberately.
- variants: field + toolbar drop arbitrary ControlVariant narrowings;
both expose all 3 (surface | outline | ghost) with new outline CSS.
- pagination demo: disambiguate siblingCount/boundaryCount as "per side"
in label + API table (Radix/MUI convention).
- docs: CHECKLIST §C-2.6 (contract token presence) + §D-7.4 (chip parity)
+ §D-7.5 (size category) added. DEMO_AUTHORING §12.7 (chip parity) +
§12.8 (size category cheatsheet) added. eidos/README +
active_architecture.md sync texts/migration nomenclature.
- PENDIENTES.md: normas N-1..N-5 implantadas en esta sesión.
Verification: 88/88 eidos tests, 0 type errors, 67/67 component:audit PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
Resumen accionable de las decisiones adoptadas. Forman parte del
eidos: theming fixes + size/variant parity batch + docs
- theme: add surface.muted + content.muted to color contract (neutral-3
+ neutral-10). Plugs 17 broken --color-content-muted and 3 broken
--color-surface-muted references in recipes/components.
- form.css: fix --color-neutral-element-hover typo → --color-neutral-hover.
- archetypes.css + events.css: replace raw hsl/rgba indigo with
color-mix(var(--color-primary-solid) …) — no raw colors left in eidos.
- combobox dark scrollbar: unscope ::-webkit-scrollbar rules in uix.css
and duplicate --uix-line on :root + :root[data-mode='dark'] so portaled
overlays (Combobox listbox, Popover, Dialog, Drawer) inherit the theme.
- sizes: 20 components expand from sm/md/lg to xs..xl (form controls,
text inputs, progress/meter, field/form) or xs..lg (nav controls:
breadcrumb, pagination, tag-group, toolbar). Composite panels keep
sm/md/lg deliberately.
- variants: field + toolbar drop arbitrary ControlVariant narrowings;
both expose all 3 (surface | outline | ghost) with new outline CSS.
- pagination demo: disambiguate siblingCount/boundaryCount as "per side"
in label + API table (Radix/MUI convention).
- docs: CHECKLIST §C-2.6 (contract token presence) + §D-7.4 (chip parity)
+ §D-7.5 (size category) added. DEMO_AUTHORING §12.7 (chip parity) +
§12.8 (size category cheatsheet) added. eidos/README +
active_architecture.md sync texts/migration nomenclature.
- PENDIENTES.md: normas N-1..N-5 implantadas en esta sesión.
Verification: 88/88 eidos tests, 0 type errors, 67/67 component:audit PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
contrato del componente y están reflejadas en los `.md` doctrinales.
### N-1 · Cobertura de tamaños
Cada componente expone los valores de `Size` que su recipe declara. El
sistema admite `xxs · xs · sm · md · lg · xl · xxl · full` . La elección
por categoría:
| Categoría | Sizes | Componentes afectados |
| --- | --- | --- |
| Form controls táctiles | `xs · sm · md · lg · xl` | checkbox, switch, toggle, radio-group, rating-group, slider |
| Inputs de texto | `xs · sm · md · lg · xl` | search-field, number-field, date-field, editable, tags-input, combobox, select |
| Progress/meter (barra escalable) | `xs · sm · md · lg · xl` | progress, meter |
| Field / Form (layout) | `xs · sm · md · lg · xl` | field, form |
| Nav controls | `xs · sm · md · lg` | breadcrumb, pagination, tag-group, toolbar |
| Sin cambio (paneles compuestos donde sm/md/lg cubre) | `sm · md · lg` | calendar, date-picker, date-range-picker, file-upload, stepper, tooltip |
| Ya en rango ampliado | `xs · sm · md · lg · xl[+full]` | avatar, dialog, drawer, popover, tabs, icon |
### N-2 · Paridad de chips en demos
Toda variante / tamaño / color declarado en el tipo del componente
**debe** aparecer como chip seleccionable en el demo. Las `Extract<…>`
arbitrarias que truncaban la unión están eliminadas (`field`,
`toolbar` ahora exponen los 3 valores de `ControlVariant` ).
Enforced por audit D-7.4.
eidos: theming fixes + size/variant parity batch + docs
- theme: add surface.muted + content.muted to color contract (neutral-3
+ neutral-10). Plugs 17 broken --color-content-muted and 3 broken
--color-surface-muted references in recipes/components.
- form.css: fix --color-neutral-element-hover typo → --color-neutral-hover.
- archetypes.css + events.css: replace raw hsl/rgba indigo with
color-mix(var(--color-primary-solid) …) — no raw colors left in eidos.
- combobox dark scrollbar: unscope ::-webkit-scrollbar rules in uix.css
and duplicate --uix-line on :root + :root[data-mode='dark'] so portaled
overlays (Combobox listbox, Popover, Dialog, Drawer) inherit the theme.
- sizes: 20 components expand from sm/md/lg to xs..xl (form controls,
text inputs, progress/meter, field/form) or xs..lg (nav controls:
breadcrumb, pagination, tag-group, toolbar). Composite panels keep
sm/md/lg deliberately.
- variants: field + toolbar drop arbitrary ControlVariant narrowings;
both expose all 3 (surface | outline | ghost) with new outline CSS.
- pagination demo: disambiguate siblingCount/boundaryCount as "per side"
in label + API table (Radix/MUI convention).
- docs: CHECKLIST §C-2.6 (contract token presence) + §D-7.4 (chip parity)
+ §D-7.5 (size category) added. DEMO_AUTHORING §12.7 (chip parity) +
§12.8 (size category cheatsheet) added. eidos/README +
active_architecture.md sync texts/migration nomenclature.
- PENDIENTES.md: normas N-1..N-5 implantadas en esta sesión.
Verification: 88/88 eidos tests, 0 type errors, 67/67 component:audit PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### N-3 · Tokens del contrato deben estar declarados
Cualquier `var(--color-X)` referenciado en recipes o en `*.css` debe
estar declarado en `generated/base.css` . La sesión añadió
eidos: theming fixes + size/variant parity batch + docs
- theme: add surface.muted + content.muted to color contract (neutral-3
+ neutral-10). Plugs 17 broken --color-content-muted and 3 broken
--color-surface-muted references in recipes/components.
- form.css: fix --color-neutral-element-hover typo → --color-neutral-hover.
- archetypes.css + events.css: replace raw hsl/rgba indigo with
color-mix(var(--color-primary-solid) …) — no raw colors left in eidos.
- combobox dark scrollbar: unscope ::-webkit-scrollbar rules in uix.css
and duplicate --uix-line on :root + :root[data-mode='dark'] so portaled
overlays (Combobox listbox, Popover, Dialog, Drawer) inherit the theme.
- sizes: 20 components expand from sm/md/lg to xs..xl (form controls,
text inputs, progress/meter, field/form) or xs..lg (nav controls:
breadcrumb, pagination, tag-group, toolbar). Composite panels keep
sm/md/lg deliberately.
- variants: field + toolbar drop arbitrary ControlVariant narrowings;
both expose all 3 (surface | outline | ghost) with new outline CSS.
- pagination demo: disambiguate siblingCount/boundaryCount as "per side"
in label + API table (Radix/MUI convention).
- docs: CHECKLIST §C-2.6 (contract token presence) + §D-7.4 (chip parity)
+ §D-7.5 (size category) added. DEMO_AUTHORING §12.7 (chip parity) +
§12.8 (size category cheatsheet) added. eidos/README +
active_architecture.md sync texts/migration nomenclature.
- PENDIENTES.md: normas N-1..N-5 implantadas en esta sesión.
Verification: 88/88 eidos tests, 0 type errors, 67/67 component:audit PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
`content.muted` y `surface.muted` al contrato y corrigió el typo
`--color-neutral-element-hover` en form.css.
Enforced por audit R-2.6.
eidos: theming fixes + size/variant parity batch + docs
- theme: add surface.muted + content.muted to color contract (neutral-3
+ neutral-10). Plugs 17 broken --color-content-muted and 3 broken
--color-surface-muted references in recipes/components.
- form.css: fix --color-neutral-element-hover typo → --color-neutral-hover.
- archetypes.css + events.css: replace raw hsl/rgba indigo with
color-mix(var(--color-primary-solid) …) — no raw colors left in eidos.
- combobox dark scrollbar: unscope ::-webkit-scrollbar rules in uix.css
and duplicate --uix-line on :root + :root[data-mode='dark'] so portaled
overlays (Combobox listbox, Popover, Dialog, Drawer) inherit the theme.
- sizes: 20 components expand from sm/md/lg to xs..xl (form controls,
text inputs, progress/meter, field/form) or xs..lg (nav controls:
breadcrumb, pagination, tag-group, toolbar). Composite panels keep
sm/md/lg deliberately.
- variants: field + toolbar drop arbitrary ControlVariant narrowings;
both expose all 3 (surface | outline | ghost) with new outline CSS.
- pagination demo: disambiguate siblingCount/boundaryCount as "per side"
in label + API table (Radix/MUI convention).
- docs: CHECKLIST §C-2.6 (contract token presence) + §D-7.4 (chip parity)
+ §D-7.5 (size category) added. DEMO_AUTHORING §12.7 (chip parity) +
§12.8 (size category cheatsheet) added. eidos/README +
active_architecture.md sync texts/migration nomenclature.
- PENDIENTES.md: normas N-1..N-5 implantadas en esta sesión.
Verification: 88/88 eidos tests, 0 type errors, 67/67 component:audit PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### N-4 · No raw colors en CSS de Eidos
`hex / rgb / hsl / named` están prohibidos en `src/uix/eidos/**/*.css`
y en `recipes/base.ts` . Todo color va por `color-mix(in srgb, var(--color-X) N%, transparent)`
o por token directo. Corregidos `archetypes.css` y `events.css`
(eidos-commit-settle indigo → primary-solid).
eidos: theming fixes + size/variant parity batch + docs
- theme: add surface.muted + content.muted to color contract (neutral-3
+ neutral-10). Plugs 17 broken --color-content-muted and 3 broken
--color-surface-muted references in recipes/components.
- form.css: fix --color-neutral-element-hover typo → --color-neutral-hover.
- archetypes.css + events.css: replace raw hsl/rgba indigo with
color-mix(var(--color-primary-solid) …) — no raw colors left in eidos.
- combobox dark scrollbar: unscope ::-webkit-scrollbar rules in uix.css
and duplicate --uix-line on :root + :root[data-mode='dark'] so portaled
overlays (Combobox listbox, Popover, Dialog, Drawer) inherit the theme.
- sizes: 20 components expand from sm/md/lg to xs..xl (form controls,
text inputs, progress/meter, field/form) or xs..lg (nav controls:
breadcrumb, pagination, tag-group, toolbar). Composite panels keep
sm/md/lg deliberately.
- variants: field + toolbar drop arbitrary ControlVariant narrowings;
both expose all 3 (surface | outline | ghost) with new outline CSS.
- pagination demo: disambiguate siblingCount/boundaryCount as "per side"
in label + API table (Radix/MUI convention).
- docs: CHECKLIST §C-2.6 (contract token presence) + §D-7.4 (chip parity)
+ §D-7.5 (size category) added. DEMO_AUTHORING §12.7 (chip parity) +
§12.8 (size category cheatsheet) added. eidos/README +
active_architecture.md sync texts/migration nomenclature.
- PENDIENTES.md: normas N-1..N-5 implantadas en esta sesión.
Verification: 88/88 eidos tests, 0 type errors, 67/67 component:audit PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### N-5 · Scrollbars portaled
Las reglas `::-webkit-scrollbar*` viven sin scope en `web/routes/uix/uix.css`
para alcanzar overlays portaleados (Combobox listbox, Popover content,
Dialog, Drawer). `--uix-line` está duplicado en `:root` + override en
`:root[data-mode='dark']` (atributo escrito por `ActiveEidos.apply()` ).
### N-6 · Picker kind = single source for input + view
Para los pickers, `kind: 'date' | 'month' | 'year'` (Chakra-style) es
el ** único** punto de configuración para variantes de granularidad.
Drives:
1. **Segments del input** : filtrado a nivel del `DateFieldProvider`
(soma). El consumer renderiza `segments` tal cual viene — no
filtra en el snippet. `kind='year'` → `YYYY` , `kind='month'` →
`MM/YYYY` , `kind='date'` → `MM/DD/YYYY` . Literales colapsados
automáticamente.
2. **View del popover** : el consumer hace branching estructural
(`{#if kind === 'year'} < YearView / > {:else if 'month'} < MonthView / > {:else} < Calendar / > {/if}`).
Las views son partes propias: `<DatePicker.YearView>` ,
`<DatePicker.MonthView>` , equivalentes en `DateRangePicker` .
Implicación: **no hay** componentes separados `MonthPicker` ,
`YearPicker` , `MonthRangePicker` , `YearRangePicker` . Esos casos son
`<DatePicker kind='X'>` / `<DateRangePicker kind='X'>` .
### N-7 · Composición sobre props para visibilidad de parts
Las parts opcionales (`Footer`, `Clear` , `Cancel` , `Close` , etc.) NO
exponen props `*Button` booleanos en el root del componente. La
visibilidad se controla por **composición** : si quieres `Clear` ,
compones `<X.Clear/>` dentro de `<X.Footer/>` . Si no lo compones, no
aparece. Si no quieres footer entero, omites `<X.Footer/>` .
Las parts renderizan siempre que se monten — sin checks internos
contra props del provider. Esto se aplica a *derivados* : el patrón
escala a cualquier componente con sub-parts opcionales (Header,
Footer, ToolbarItem, etc.).
Demos: las parts se envuelven en `{#if showX}` con state local del
demo para dar el control UI, pero las parts en sí no leen ese state.
refactor(color-picker): channel slider composes generic SliderProvider + N-8 norm
Drops ColorPickerChannelSliderProvider / TrackProvider / ThumbProvider
(~200 lines of duplicated pointer/keyboard/ARIA handling) and rewrites
`components/color-picker-channel-slider.svelte` to compose
SliderProvider underneath. The channel slider now keeps only the
channel-aware bridge: setChannel writes the value, channelGradient
paints the track.
What the picker gains by reusing Slider
---------------------------------------
- sema events: `slider:handle-pick`, `slider:handle-drag`,
`slider:commit-set` now flow through the channel sliders (they were
silent before — the Sema layer had no perceptual hook on channel
drag/commit).
- single pointer/keyboard implementation: Arrow/Home/End/PageUp/PageDown,
multi-touch, focus trap, RTL, step-snap — all from SliderProvider.
- ARIA: role=slider, aria-valuenow/min/max, aria-orientation, tabindex
managed by the slider's thumb provider.
- recipe tokens: channel sliders consume `--slider-*` (sizes, radii,
shadows) so they stay in lockstep with the standalone Slider and
with TimePicker.HourSlider / .MinuteSlider / .SecondSlider. The
`--color-picker-channel-slider-*` tokens are removed.
Public API impact
-----------------
- `<ColorPicker.ChannelSliderTrack>` and `<ColorPicker.ChannelSliderThumb>`
remain as part names but now re-export `Slider.Range` /
`Slider.Thumb`. Consumers that compose them inline keep working.
- The inner DOM changes: `[data-slider]` / `[data-slider-thumb]` /
`[data-slider-range]` (governed by the slider morfo) replace
`[data-color-picker-channel-slider-track]` /
`[data-color-picker-channel-slider-thumb]`. The wrapper still emits
`[data-color-picker-channel-slider][data-channel]` so per-channel
CSS targeting works; the gradient is exposed via
`--cp-channel-gradient` and routed onto the slider's track ::before.
- Morfo: drops `channel-slider-track` and `channel-slider-thumb` parts
(the slider morfo owns those contracts now). `channel-slider`
remains as the wrapper marker with `data-channel`.
- Eidos: deletes `color-picker-channel-slider-track.svelte` and
`color-picker-channel-slider-thumb.svelte`; `index.ts` re-points
`ChannelSliderTrack` / `ChannelSliderThumb` at the slider eidos
components.
New norm N-8 added to PENDIENTES.md
-----------------------------------
"Reutilizar componentes ya definidos en componentes complejos siempre
que no supongan una pérdida de características demostrable." Documented
with this refactor as the worked example.
Checks
------
- 67/67 component-audit PASS
- 40/40 morfo:check PASS
- svelte-check 0 errors / 0 warnings
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### N-8 · Reutilizar componentes ya definidos en componentes complejos
Cuando un componente complejo (picker, combobox, color-picker, etc.)
necesita un sub-control que ya existe como componente independiente
(Slider, Popover, Calendar, Field, etc.), **debe componerlo en vez de
reimplementarlo**. Sólo se justifica un fork si reusarlo causaría una
pérdida de características concreta y demostrable.
Beneficios:
1. **Una sola fuente de eventos sema** . El sub-control emite sus
eventos canónicos (`slider:handle-pick`, `slider:commit-set` ,
`popover:close-dismiss` , etc.) que el composite hereda
automáticamente — sin reimplementar la dimensión perceptiva.
2. **Una sola implementación de pointer/keyboard/ARIA** . Bugs
corregidos en el componente raíz se propagan a todos los composites
que lo usan. Sin duplicación de drag, focus trap, etc.
3. **Tokens del recipe unificados** . `--slider-track-size` ,
`--popover-content-padding` , etc. se setean en un único recipe;
todos los composites consumen los mismos.
4. **Superficie pública estable** . La API del composite (parts +
eventos) se reduce a su lógica diferenciadora; el resto cae del
sub-control.
Caso aplicado 2026-05-21: ColorPicker.ChannelSlider deja de tener su
propio `ColorPickerChannelSliderProvider` con pointer handlers
duplicados; ahora compone `SliderProvider` por debajo. Channel-aware
behavior queda en una sola función bridge (`setChannel` + gradient
inline en `--cp-channel-gradient` ). Resultado: − 200 líneas en soma,
eventos `slider:handle-pick/drag/commit-set` propagados, tokens
unificados con time-picker / standalone Slider.
Segundo caso 2026-05-21 — **PickerShell** . El Footer + Clear/Cancel/
Close de los pickers eran cuatro archivos `.svelte` casi idénticos
por picker (date-picker, time-picker, color-picker). Extracción a:
- `src/uix/soma/components/picker-shell/` — `pickerShellContext` +
`PickerShellHandle` interface (`getMode / commit / cancel / clear`).
- `src/uix/eidos/components/picker-shell/` — parts compartidos
`<PickerShell.Footer/Clear/Cancel/Close>` que leen el handle.
- `src/uix/eidos/components/picker-shell/picker-shell.css` — CSS
canónica `[data-picker-footer/clear/cancel/close]` .
Cada provider registra su handle en el context via
`pickerShellContext.set(this.pickerShellHandle)` . El namespace de cada
picker eidos re-exporta `X.Footer/Clear/Cancel/Close` apuntando a los
componentes compartidos — la API pública no cambia. Aplicado al
ColorPicker en este commit. Migración pendiente para date-picker y
time-picker (issue separado).