Tokens y temas
Cada decisión visual es una propiedad personalizada con el prefijo --iv-, generada desde una única fuente JSON. Puedes sobrescribir cualquiera de ellas en :root o en un ámbito concreto; no hay que recompilar nada.
:root {
--iv-color-primary: #4338CA; /* tu marca */
--iv-color-on-primary: #FFFFFF;
--iv-radius-md: 0.25rem;
}
.checkout { --iv-button-radius: var(--iv-radius-full); } /* local al componente */Temas
data-iv-theme acepta light (el valor por defecto cuando falta), dark y system. Los ámbitos se anidan y gana el valor explícito más cercano; system sigue a prefers-color-scheme sin JavaScript ni almacenamiento.
<div class="iv-grid iv-u-gap-4 iv-u-grid-cols-1 iv-u-md-grid-cols-3">
<section class="iv-card" data-iv-theme="light"><div class="iv-card__body"><h3 class="iv-card__title">Light scope</h3><button class="iv-button iv-button--primary" type="button">Primary</button></div></section>
<section class="iv-card" data-iv-theme="dark"><div class="iv-card__body"><h3 class="iv-card__title">Dark scope</h3><button class="iv-button iv-button--primary" type="button">Primary</button>
<section class="iv-card iv-u-mt-4" data-iv-theme="system"><div class="iv-card__body"><p class="iv-u-m-0">System inside dark follows the OS.</p></div></section>
</div></section>
<section class="iv-card" data-iv-theme="system"><div class="iv-card__body"><h3 class="iv-card__title">System scope</h3><button class="iv-button iv-button--primary" type="button">Primary</button></div></section>
</div>El módulo opcional theme añade getTheme(), setTheme(theme, { persist }), resolveTheme() y restoreTheme(), y emite iv:themechange sobre document. La persistencia hay que pedirla expresamente. Para evitar un parpadeo antes de que se aplique el tema guardado, añade un pequeño script en línea dentro de <head>; con una CSP estricta, permítelo por hash o por nonce.
Colores semánticos
| Token | Claro | Oscuro |
|---|---|---|
--iv-color-bg | #FFFFFF | #04070F |
--iv-color-surface | #F5F7FC | #070D1C |
--iv-color-surface-raised | #FFFFFF | #0C1330 |
--iv-color-text | #0B1230 | #EEF2FB |
--iv-color-text-muted | #4F5B7A | #A8B3CC |
--iv-color-border | #D3DAEA | #33406A |
--iv-color-border-strong | #6B7896 | #6B7896 |
--iv-color-primary | #1D4FC4 | #66B1FF |
--iv-color-on-primary | #FFFFFF | #06122B |
--iv-color-primary-hover | #1A3FA8 | #8FC6FF |
--iv-color-primary-active | #172F7A | #3D94FF |
--iv-color-primary-subtle | #EAF4FF | rgb(102 177 255 / 0.12) |
--iv-color-accent | #0B6B8A | #73DFFF |
--iv-color-on-accent | #FFFFFF | #06122B |
--iv-color-success | #4F7A12 | #8BBF3A |
--iv-color-on-success | #FFFFFF | #06122B |
--iv-color-success-subtle | #F1F8E4 | rgb(139 191 58 / 0.12) |
--iv-color-danger | #C22E26 | #FF9AA4 |
--iv-color-on-danger | #FFFFFF | #06122B |
--iv-color-danger-subtle | #FFF1F0 | rgb(255 154 164 / 0.12) |
--iv-color-warning | #8F5C00 | #FBBF24 |
--iv-color-on-warning | #FFFFFF | #06122B |
--iv-color-warning-subtle | #FFF8E6 | rgb(251 191 36 / 0.12) |
--iv-color-info | #3D47C2 | #8B95FF |
--iv-color-on-info | #FFFFFF | #06122B |
--iv-color-info-subtle | #EEF0FF | rgb(139 149 255 / 0.12) |
--iv-color-focus | #1D4FC4 | #73DFFF |
--iv-color-overlay | rgb(11 18 48 / 0.55) | rgb(2 5 12 / 0.78) |
--iv-color-hover-surface | rgb(11 18 48 / 0.04) | rgb(230 240 255 / 0.05) |
--iv-color-primary-border | rgb(29 79 196 / 0.55) | rgb(102 177 255 / 0.5) |
Objetivos de contraste: 4.5:1 para el texto y 3:1 para los controles y el foco sobre sus superficies. Los valores de arriba se comprobaron con la fórmula de WCAG; se vuelven a medir en cada publicación.
La capa expresiva
Seis tokens añadidos en la v0.6. Ponen nombre a las recetas que el pulido visual venía repitiendo a mano en una docena de módulos —una sombra, un tinte al pasar el puntero, un borde de marca, un halo de foco y dos espaciados de letra—, de modo que ahora todos leen el mismo valor de un solo sitio. Al llegar no cambiaron nada a la vista: son nombres para lo que ya estaba dibujado.
| Token | Claro | Oscuro | Dónde se usa |
|---|---|---|---|
--iv-shadow-ambient | 0 2px 10px rgb(11 18 48 / 0.10) | 0 0 1px 1px #1C2544, 0 2px 10px rgb(0 0 0 / 0.5) | Elevación en reposo de tarjeta, tabla envuelta, alerta, acordeón y botón. Un token en lugar de cinco recetas. |
--iv-color-hover-surface | rgb(11 18 48 / 0.04) | rgb(230 240 255 / 0.05) | Tinte al pasar el puntero en pies de tarjeta, diálogo y drawer, pestañas y el campo del selector. Las filas de tabla y de menú conservan el tinte de marca de primary-subtle. |
--iv-color-primary-border | rgb(29 79 196 / 0.55) | rgb(102 177 255 / 0.5) | Contorno de marca: botón secundario, hover de campos, paginación y cualquier borde que deba leerse como de la marca. |
--iv-focus-halo | 0 0 2px 3px rgb(29 79 196 / 0.35) | 0 0 3px 2px rgb(102 177 255 / 0.32) | El halo que acompaña al anillo de foco en campos, botones, paginación, migas, marcadores del stepper y el botón del navbar. Siempre junto al anillo, nunca en su lugar. |
--iv-tracking-tight | -0.011em | -0.011em | Espaciado de letra en títulos de tarjeta, diálogo, drawer y cifra. |
--iv-tracking-caps | 0.06em | 0.06em | Espaciado de letra en versalitas: cabeceras de tabla, leyendas de fieldset, encabezados del megamenú y de la paleta, etiquetas de cifra. |
Los dos colores aparecen también en la tabla de arriba, porque son colores semánticos como los demás. Los seis son propiedades personalizadas normales: sobrescríbelos en :root o en un ámbito y todos los componentes que los leen te siguen.
Escalas
| Familia | Tokens |
|---|---|
| Espacio | --iv-space-0 … 16 (pasos de 0.25rem hasta 1.5rem, y después 2, 2.5, 3 y 4rem) |
| Tipografía | --iv-text-xs … 4xl, --iv-leading-*, --iv-weight-*, --iv-font-sans|mono |
| Forma | --iv-radius-sm|md|lg|full, --iv-border-width, --iv-shadow-1|2|3 |
| Foco | --iv-focus-width, --iv-focus-offset, --iv-color-focus |
| Movimiento | --iv-motion-fast|base|slow (120/180/220 ms; 0 ms con la reducción de movimiento), --iv-ease-out |
| Capas | --iv-z-dropdown|drawer|dialog|toast |
| Medidas | --iv-measure (68ch), --iv-container-max (75rem), --iv-content-max (90rem) |
| Puntos de ruptura | sm 30em · md 48em · lg 64em · xl 80em · 2xl 90em. Se resuelven al compilar; no están disponibles como propiedades personalizadas dentro de las media queries. |