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

5.9 KiB

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 (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:

  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.