You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/web/routes/temas/grafito/README.md

113 lines
5.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Tema · Untitled UI · Carbon
Demo de theming en vivo para activeUIX sobre el sistema de Eidos. Es a la vez
un **tema completo** (`untitled-ui-light` / `untitled-ui-dark`) y un **playground**
que muestra todos los elementos del tema: roles de color, rampas físicas de 12
pasos, superficies, tipografía, espaciado, radios, sombras, tamaños y el aspecto
real de cada control con sus variantes — más la capa semántica (sema).
Ruta: `/temas/untitled-ui`.
## Identidad del tema
Fiel a [untitledui.com](https://untitledui.com) (tipografía Inter, sombras en
capas, radios de 8px, anillos de foco suaves) pero con una decisión deliberada:
el **primario es carbón** (grafito casi negro `#1F2024`), monocromo al estilo
Vercel / Linear — **no** el violeta de marca de UUI. El violeta de UUI (`#7F56D9`)
se reubica como **secundario**.
Los 9 roles canónicos del framework quedan retintados con jerarquía diferenciada
(ninguno se repite):
| Rol | Escala | Color | Papel |
| --- | --- | --- | --- |
| `primary` | carbon | `#1F2024` | Acción principal, monocroma. Texto auto-invertido vía `slots.contrast: '1'`. |
| `secondary` | violet | `#7F56D9` | Violeta de marca UUI. |
| `tertiary` | blue | `#1570EF` | Acento azul. |
| `neutral` | gray | `#667085` | Gris frío UUI. |
| `affirm` | teal | — | Positivo ligero (baja activación). |
| `fulfill` | green | — | Éxito / completado. |
| `risk` | amber | `#DC6803` | Aviso. |
| `threat` | red | `#D92D20` | Error / peligro. |
| `loss` | plum | `#7A3AAD` | Pérdida grave: violeta sombrío, posterior (más oscuro que el secundario). |
Otros tokens del tema:
- **Tipografía**: Inter (`primary` / `secondary` / `display`), Roboto Mono (`mono`).
Letter-spacing negativo en los displays (`hero` / `h1` / `h2` a `-0.02em`, `h3` a `-0.01em`).
- **Radios**: escala con `md = 8px` como base UUI (`none` → `full`).
- **Foco**: `focusRing` con `offset 1px` + `width 3px`; el halo lavanda se pinta
en `untitled-ui.css` (`--uui-ring`, derivado de `--color-secondary-solid`).
- **Sombras**: set en capas estilo UUI (light + dark).
- **Densidad**: `compact` / `comfortable` / `spacious` — **funcional**, escala el
espaciado y la altura de los controles (ver «Correcciones del engine» abajo).
El tema vive en `_lib/untitled-ui.ts` como un `EidosConfig` independiente
(no parchea el `base`): define escalas light/dark, el `ColorRoleMap` y los dos
themes. No inventa variants ni roles nuevos — solo retinta lo canónico.
## Componentes mostrados
Foundations (markup propio sobre tokens del tema): roles + rampas + superficies,
tipografía, espaciado / radio / sombra / tamaño.
Controles eidos reales, todos dirigidos por el tema:
- **Button** (6 variants × roles × tamaños × estados)
- **Badge**
- **Form**: Field, Select, Checkbox, RadioGroup, Switch, Slider
- **Feedback**: Banner, Progress, Avatar, Card
- **Tabs**, **Accordion**
- **Toggle**, **ToggleGroup** (single + multiple, segmentado)
- **Toolbar**
- **Overlays**: Popover, Dialog (portaleados)
- **Menús**: Menubar, DropdownMenu, ContextMenu, Tooltip (portaleados)
- **Semántica**: la capa sema (sonido + haptic + reacción visual `data-event-*`)
encendida en el layout vía `createActiveUix({ events: { sound, haptic, components } })`.
## Estructura
| Archivo | Rol |
| --- | --- |
| `_lib/untitled-ui.ts` | Config del tema (`EidosConfig`): escalas, roles, themes light/dark. Exporta `THEME_ROLES`, `THEME_SCALES`, `COLOR_STEPS`. |
| `+layout@.svelte` | Raíz de composición. Arranca `ActiveUix` + `Soma` + `ActiveEidos` con el tema. Posee modo (claro/oscuro) y densidad como fuentes visuales. El `@` resetea la herencia del chrome de `/uix`. |
| `+page.svelte` | La página demo. |
| `theme.css` | Chrome del shell + helpers de layout (`[data-temas-*]`). |
| `untitled-ui.css` | Capa de pulido scoped a `[data-theme^='untitled-ui']`: anillo lavanda, sombras de control, bordes. |
## Correcciones del engine de theming (dependencias)
Este tema fue el primer consumidor que reveló dos bugs del engine de Eidos,
corregidos **a nivel engine** (sin deuda en el tema). Documentados en detalle en
[`src/uix/eidos/THEMING.md` §20](../../../../src/uix/eidos/THEMING.md):
1. **Densidad inerte** — `data-density` no afectaba a nada. Fix: `renderStaticCss`
emite `space` y `control-height` como `calc(value * var(--density-*-scale))`,
de modo que `[data-density]` reescala de verdad. (§20.1)
2. **`contrast` ilegible sobre sólidos** — el texto sobre el sólido de color
resolvía al paso 12 de la escala (casi invisible). Fix: el slot `contrast` por
defecto resuelve a `var(--color-content-on-solid, …)`. Por eso el primario
carbón lleva texto casi blanco sin configurar nada extra. (§20.2)
## Hallazgo de autoría: `bind:value` debe respetar el default `$bindable`
La página tuvo un síntoma engañoso: bajo SSR renderizaba completa (~1.1 MB) pero
la hidratación en cliente **desmontaba** casi todo el árbol (los componentes
quedaban como anclas vacías `<!---->`), sin error visible en consola. Parecía un
fallo de hidratación de los componentes con portal.
La causa real era un único `bind:value={menubarValue}` con
`menubarValue = $state(undefined)`, mientras `<Menubar>` declara
`value = $bindable('')`. Svelte 5 lanza `props_invalid_value` («Cannot do
`bind:value={undefined}` when `value` has a fallback value») **durante** la
hidratación; el error aborta el render de la página y desmonta el árbol.
Lección: al usar `bind:` contra un prop con default `$bindable`, el estado local
debe inicializarse con un valor del mismo tipo que el default — nunca `undefined`.
Aquí: `menubarValue = $state('')` y `align = $state<string[]>(['left'])`
(`ToggleGroup` usa `value = $bindable([])`, también para `type="single"`).
No era un bug del engine de theming ni de los portales: los componentes con portal
(Popover / Dialog / Menubar / DropdownMenu / Tooltip) renderizan, hidratan y abren
correctamente cuando el `bind:value` es válido.

Powered by TurnKey Linux.