Saltar al contenido principal
Version: Next (5.0)

Design tokens y modo oscuro

El cliente AngularJS expone su aspecto como un conjunto pequeño de propiedades personalizadas de CSS, los design tokens, con nombre --awe-*. Los componentes, tus propias hojas de estilo, Tailwind (@theme) y cualquier cliente nuevo leen los tokens; los temas y el modo oscuro solo cambian los valores que hay detrás. Los tokens se emiten desde un único fichero LESS, awe-client-angular/src/main/resources/less/awe/tokens.less, sobre la compilación LESS actual: LESS y Bootstrap 3 siguen ahí y nada de lo que hace hoy un producto deja de funcionar.

Cómo un tema se convierte en tokens​

variable de tema --primary-color la define .theme-<nombre>, .theme-<nombre>.dark (temas LESS, temas de base de datos)
│
▼
design token --awe-color-primary se declara en el body (.base-theme) y en :root, nunca la define un tema
│
▼
consumidores LESS (@primary-color), componentes, Tailwind @theme, el cliente React
  • Una variable de tema es lo que sobrescribe un tema. Son las variables que AWE ya tenía (--primary-color, --panel-background-color...) y las que la pantalla de mantenimiento de Temas escribe en la base de datos, de modo que todo tema existente, tema de base de datos y tema de producto sigue funcionando sin cambios.
  • Un token es el nombre público. Se declara en body.base-theme (y en :root para lo que queda fuera del body), así que se resuelve con las variables de tema del tema y del modo activos. Cambiar de tema o de modo cambia las variables de tema y los tokens las siguen.
  • Cada token lee la variable LESS del mismo significado (@primary-color es var(--primary-color, <valor por defecto>)), por lo que un token siempre tiene valor por defecto, y un producto que sobrescribe @primary-color en su LESS sigue funcionando.

Lee los tokens, no los definas. Para cambiar el aspecto, sobrescribe en tu tema la variable de tema de las tablas siguientes.

Modo del tema: claro, oscuro y el sistema operativo​

El modo es una clase del body junto al tema (<body class="base-theme theme-default dark">):

Clase del bodySignificado
darkEl usuario eligió el modo oscuro (botón de información, guardado en las preferencias del usuario)
lightEl usuario eligió el modo claro
ningunaEl usuario no eligió: decide el sistema operativo mediante prefers-color-scheme

Cada tema declara sus variables oscuras una sola vez. Se usan para .theme-<nombre>.dark y, para un usuario que no eligió, dentro de @media (prefers-color-scheme: dark) para .theme-<nombre>:not(.light):not(.dark). La elección explícita del usuario siempre gana al sistema operativo.

Un fichero de tema declara ambos con un mixin:

.theme-sunset {
--primary-color: #7a6f6f;
// ...las variables claras
}

// Dark mode: chosen by the user (.dark) or, when not chosen, by the OS (prefers-color-scheme)
@theme-sunset-dark: {
--primary-color: #7a6f6f;
// ...las variables oscuras
};
.awe-theme-dark(sunset; @theme-sunset-dark);

Los temas guardados en la base de datos obtienen el mismo par de reglas desde /css/themeVariables.css.

Un producto que no debe seguir al sistema operativo​

Define la variable LESS después de importar AWE (el usuario puede seguir eligiendo el modo oscuro, solo se ignora el sistema operativo):

@awe-follow-os-color-scheme: false;

Los temas guardados en la base de datos usan el mismo interruptor en el servidor: defina awe.application.theme-follow-os-color-scheme=false (por defecto true) para que /css/themeVariables.css no emita la regla prefers-color-scheme. Defina ambos para desactivar el sistema operativo.

Referencia de tokens​

Los nombres de los tokens son un contrato: no cambian entre versiones de la línea. Se pueden añadir tokens nuevos.

Color​

TokenSignificadoVariable de tema a sobrescribirVariable LESS
--awe-color-themeColor de acento del tema--theme-color@theme-color
--awe-color-textTexto por defecto--text-color@text-color
--awe-color-primaryAcciones principales, selección, enlaces del tema--primary-color@primary-color
--awe-color-on-primaryTexto sobre el color primario--primary-text-color@primary-text-color
--awe-color-secondaryBotones por defecto y controles neutros--secondary-color@secondary-color
--awe-color-on-secondaryTexto sobre el color secundario--secondary-text-color@secondary-text-color
--awe-color-backgroundFondo de la página--primary-background-color@primary-background-color
--awe-color-surfaceSuperficie secundaria (pies de panel, zonas de campos)--secondary-background-color@secondary-background-color
--awe-color-borderBorde por defecto--border-color@border-color
--awe-color-shadowColor de las sombras--shadow-color
--awe-color-menuFondo del menú principal--primary-menu-color@primary-menu-color
--awe-color-menu-accentHover y resaltado del menú principal--secondary-menu-color@secondary-menu-color
--awe-color-menu-textTexto del menú principal--menu-text-color@menu-text-color
--awe-color-navbarFondo de la barra de navegación--primary-navbar-color@primary-navbar-color
--awe-color-navbar-accentCabecera de la barra de navegación--secondary-navbar-color@secondary-navbar-color
--awe-color-navbar-textTexto de la barra de navegación--navbar-text-color@navbar-text-color
--awe-color-navbar-dropdownMenús desplegables--navbar-dropdown-color@navbar-dropdown-color
--awe-color-panelFondo de paneles y diálogos--panel-background-color@panel-background-color
--awe-color-panel-headerFondo de la cabecera del panel--panel-header-color@panel-header-color
--awe-color-panel-borderBorde del panel--panel-border-color@panel-border-color
--awe-color-panel-textTexto sobre la cabecera del panel--panel-text-color@panel-text-color
--awe-color-grid-headerCabecera de la grid--grid-header-color@grid-header-color
--awe-color-grid-borderBordes de la grid--grid-border-color@grid-border-color
--awe-color-skeletonRelleno de los esqueletos de carga de grids, criterios, botones y gráficos (derivado del borde de la grid)
--awe-color-skeleton-highlightBrillo animado de los esqueletos de carga
--awe-color-disabledFondo de un control deshabilitado--disabled-color@disabled-color
--awe-color-disabled-borderBorde de un control deshabilitado--disabled-border-color@disabled-border-color
--awe-color-disabled-textTexto de un control deshabilitado--disabled-text-color@disabled-text-color
--awe-color-requiredFondo de un campo obligatorio--required-color@required-color
--awe-color-loading-barBarra de carga--loading-bar-color@loading-bar-color
--awe-color-dangerError--danger-color@danger-color
--awe-color-warningAviso--warning-color@warning-color
--awe-color-successÉxito--success-color@success-color
--awe-color-infoInformación--info-color@info-color

Tipografía​

TokenSignificadoVariable de tema a sobrescribirVariable LESS
--awe-font-family-baseFuente de la aplicación@font-family-base
--awe-font-family-monospaceFuente de código@font-family-monospace
--awe-font-size-baseTamaño de fuente por defecto--primary-font-size@primary-font-size
--awe-font-size-smallTexto pequeño--secondary-font-size@secondary-font-size
--awe-line-height-baseAltura de línea por defecto@line-height-base
--awe-font-weight-normalPeso normal
--awe-font-weight-boldPeso negrita

Espaciado, radio, sombra y tamaño​

TokenValorVariable de tema a sobrescribirVariable LESS
--awe-space-2xs2px
--awe-space-xs5px
--awe-space-sm10px (margen de panel pequeño)@panel-margin-sm
--awe-space-md15px (margen de panel mediano)@panel-margin-md
--awe-space-lg20px (margen de panel grande)@panel-margin-lg
--awe-space-xl30px
--awe-radiusRadio por defecto--border-radius@border-radius
--awe-radius-smLa mitad del radio por defecto
--awe-radius-lgEl doble del radio por defecto
--awe-radius-fullPíldoras y círculos
--awe-shadow-smElevación pequeña--shadow-color
--awe-shadow-mdElevación media--shadow-color
--awe-shadow-lgElevación grande--shadow-color
--awe-size-header-heightAltura de la barra de navegación--header-height@main-navbar-height
--awe-size-menu-widthAncho del menú principal@main-menu-width

Usar los tokens​

En tu CSS o LESS:

.my-card {
background: var(--awe-color-panel);
color: var(--awe-color-text);
border: 1px solid var(--awe-color-border);
border-radius: var(--awe-radius);
box-shadow: var(--awe-shadow-sm);
padding: var(--awe-space-md);
}

Cambian con el tema y con el modo sin hacer nada más. Un producto que tiene sus propias variables LESS las conserva: compilan como antes y los tokens que las leen las siguen.

Correspondencia con Tailwind​

Los tokens son lo que adopta Tailwind v4 (@theme, issue #755). Cada token se corresponde uno a uno, sin renombrarlo:

@theme inline {
--color-primary: var(--awe-color-primary);
--color-on-primary: var(--awe-color-on-primary);
--color-surface: var(--awe-color-panel);
--color-border: var(--awe-color-border);
--radius-awe: var(--awe-radius);
--shadow-awe-md: var(--awe-shadow-md);
--spacing-awe-md: var(--awe-space-md);
}

Usa @theme inline para que las utilidades mantengan la referencia var(--awe-...) y el modo oscuro se aplique sin clases de utilidad adicionales.

El cliente React​

El cliente React no usa los temas LESS: usa los temas de PrimeReact. Para que sus páginas puedan leer los mismos nombres, declara en awe-client-react/src/main.css los tokens que tienen un equivalente directo en PrimeReact:

TokenVariable de PrimeReact
--awe-color-primary--primary-color
--awe-color-on-primary--primary-color-text
--awe-color-text--text-color
--awe-color-background--surface-ground
--awe-color-surface, --awe-color-panel--surface-card
--awe-color-border--surface-border
--awe-color-skeleton, --awe-color-skeleton-highlightFondo y brillo de .p-skeleton (temas sky y sunset)
--awe-color-danger, --awe-color-warning, --awe-color-success, --awe-color-info--danger-color, --warning-color, --success-color, --info-color
--awe-font-family-base--font-family
--awe-radius--border-radius

El cliente React todavía no tiene modo oscuro: una página React lee los mismos nombres y obtiene los valores claros.

Comprobar un cambio​

awe-client-angular/src/test/jest/styles/designTokens.test.js compila toda la build LESS y comprueba que cada tema conserva sus variables (claro y oscuro, contra themes.baseline.json, tomado antes de los tokens), que las reglas oscuras del sistema operativo coinciden con las reglas oscuras explícitas, que cada token --awe-* se emite y está escrito en esta guía, y que el LESS de un producto sigue compilando. El test de navegador ThemeAndModeIT cambia el tema y el modo oscuro en la aplicación.