ng-hub-ui-ds
La base de design tokens compartida de la familia ng-hub-ui: las variables CSS --hub-ref-* (primitivas) y --hub-sys-* (semánticas), con claro/oscuro y 8 temas. Impórtala una vez y toda la familia lee la misma paleta.
¿Qué es y para qué sirve?
Su función es homogeneizar y cablear las variables de estilo a lo largo de todas las bibliotecas de la familia. Cada librería se tematiza con variables --hub-* pero no las define: las consume. Este paquete es la fuente de verdad única que las conecta, de modo que:
- Una sola paleta alimenta panels, forms, calendar, board… a la vez.
- Re-tematizas una vez (un token) y el cambio se propaga a toda la familia.
- Modo oscuro y 8 temas listos, conmutables con un atributo.
- La usas también en tu propio CSS, así tu UI casa con los componentes.
El cableado se está desplegando biblioteca a biblioteca: más abajo, en la familia, está el estado de integración de cada una. ¿Buscas el catálogo completo de tokens? Está en la referencia de tokens.
Instalación e importación
Sin dependencias: es CSS/SCSS puro. Impórtalo una sola vez, en la raíz de tu app.
Instalar
npm install ng-hub-ui-dsCSS drop-in (cualquier app, sin Sass)
@import 'ng-hub-ui-ds/styles/tokens/hub-tokens.css';o en angular.json:
"styles": [
"node_modules/ng-hub-ui-ds/styles/tokens/hub-tokens.css",
"src/styles.scss"
]Código SCSS (si usas Sass)
@use 'ng-hub-ui-ds/styles/tokens/hub-tokens';Arquitectura: las dos capas
--hub-ref-*
Valores crudos sin contexto: rampas de color, espaciado, radios, tipografía.
--hub-ref-color-blue-500--hub-sys-*
Asignaciones con significado que consumen los componentes.
--hub-sys-color-primary Regla de oro: los componentes referencian solo tokens sys; los sys apuntan a los ref. Cambiar un sys re-tematiza; cambiar un ref ajusta la paleta base.
Colores semánticos · temas en vivo
El set es abierto: 9 variantes por defecto (5 cromáticas + 4 neutrales) y las que tú añadas. Cada acento expone una familia uniforme de roles — subtle, border-subtle, emphasis y el par de contraste on. Cambia el tema y observa cómo toda la paleta se re-colorea.
Crea tu tema · cambia solo los colores base
Define únicamente el color base de cada familia semántica. El resto (subtle, border-subtle, emphasis, on) se deriva automáticamente con color-mix / relative color — y los componentes de abajo se re-tematizan en vivo, demostrando el cableado compartido.
Componentes en vivo
.mi-tema {
/* define SOLO el color base de cada familia */
--hub-sys-color-primary: #6d28d9;
/* el resto se deriva en runtime con color-mix / relative color — nada que mantener */
--hub-sys-color-primary-subtle: color-mix(in oklch, var(--hub-sys-color-primary) 12%, var(--hub-sys-surface-page));
--hub-sys-color-primary-border-subtle: color-mix(in oklch, var(--hub-sys-color-primary) 35%, var(--hub-sys-surface-page));
--hub-sys-color-primary-emphasis: color-mix(in oklch, var(--hub-sys-color-primary) 80%, var(--hub-sys-color-ink));
--hub-sys-color-primary-on: oklch(from var(--hub-sys-color-primary) clamp(0, (0.62 - l) * 1000, 1) 0 h);
}La familia · estado de integración
Toda la familia lee estos tokens. El badge indica si la biblioteca ya está cableada a --hub-sys-* (se re-tematiza con el design-system) o está pendiente de cablear (la abordamos luego). Pulsa cualquiera para ver sus ejemplos.
Cómo modificarlo
1. Sobrescribir un token (CSS) — el camino principal
Cada valor es una variable CSS, así que re-tematizar es una línea y cascada a toda la familia:
:root {
--hub-sys-color-primary: #7c3aed;
--hub-sys-color-primary-subtle: #ede9fe;
--hub-sys-color-primary-emphasis: #5b21b6;
}2. Añadir tu propio acento
Define una familia --hub-sys-color-<nombre> y los componentes que aceptan una variante semántica la recogen sin cambios. Pruébalo aquí en vivo:
color-mix. :root {
--hub-sys-color-brand: #9333ea;
--hub-sys-color-brand-subtle: #f3e8ff;
--hub-sys-color-brand-border-subtle: #d8b4fe;
--hub-sys-color-brand-emphasis: #6b21a8;
}
<!-- en cualquier componente que acepte una variante semántica -->
<hub-panel appearance="alert" variant="brand">Aviso de marca</hub-panel> Con solo --hub-sys-color-brand ya funciona (los componentes derivan el resto con color-mix). Define la familia completa cuando quieras tintes exactos.
… o predefínelo en el mapa abierto (Sass)
Si usas Sass, amplía el mapa abierto de acentos antes de incluir el paquete con $hub-accents-extra. Solo se recompila el ds — nunca las librerías— y cada variante nueva obtiene su familia completa (subtle · border-subtle · emphasis · on):
// Añade tus propias variantes — solo recompila el ds, nunca las librerías.
@use 'ng-hub-ui-ds/styles/tokens/hub-tokens' with (
$hub-accents-extra: (
brand: #ff6b00,
accent: #00b8d9,
tertiary: #9c36b5
)
);
// brand · accent · tertiary obtienen subtle · border-subtle · emphasis · on automáticamente.3. Crear un tema propio
[data-theme='corporate'] {
--hub-sys-color-primary: #0033a0;
--hub-sys-surface-page: #fbfcff;
--hub-sys-text-primary: #0a1f44;
/* …el resto de tokens que difieran del base */
}Funciones SCSS: cómo se genera por dentro
Las familias de color semántico no se escriben a mano: el set de acentos es un mapa abierto con !default y la familia se deriva con un @each sobre map.keys($hub-accents). Por eso añadir un color (o nueve) es uniforme y sin boilerplate: toda clave del mapa obtiene su familia automáticamente.
// El set de acentos es un mapa ABIERTO con !default — añade los que quieras.
$hub-accents: (
primary: …, secondary: …, success: …, danger: …, warning: …,
info: …, neutral: …, light: …, dark: …
) !default;
// La familia se deriva UNA vez en :root, iterando TODAS las claves del mapa,
// así que cualquier acento que añadas obtiene su familia gratis.
@mixin hub-color-derive() {
@each $name in map.keys($hub-accents) {
--hub-sys-color-#{$name}-subtle: color-mix(in oklch, var(--hub-sys-color-#{$name}) 12%, var(--hub-sys-surface-page));
--hub-sys-color-#{$name}-emphasis: color-mix(in oklch, var(--hub-sys-color-#{$name}) 80%, var(--hub-sys-color-ink));
--hub-sys-color-#{$name}-on: oklch(from var(--hub-sys-color-#{$name}) clamp(0, (0.62 - l) * 1000, 1) 0 h);
}
}Para la mayoría de casos no necesitas tocar el SCSS: la sobrescritura de variables CSS cubre re-tematizar y añadir acentos. El mapa + mixin es la mecánica interna, útil si contribuyes al paquete.
Capa estructural · tokens en vivo
Además del color, el ds define una capa estructural canónica: escala de spacing (--hub-ref-space-*), sizing y fracciones (--hub-sys-size-*), grid (--hub-sys-grid-columns, gutters) y una escala de gap semántica (--hub-sys-gap-*). Todo abajo se pinta consumiendo esas variables.
Escala de spacing · --hub-ref-space-0…7
Escala de gap · --hub-sys-gap-0…5
Fracciones de ancho · --hub-sys-size-*
Grid auto-fit + container widths
/* Tokens estructurales canónicos (ref → sys) */
gap: var(--hub-sys-gap-3); /* escala de spacing */
padding-inline: var(--hub-ref-space-4);
max-width: var(--hub-sys-container-max-width-lg);
grid-template-columns: repeat(var(--hub-sys-grid-columns), minmax(0, 1fr));
/* Mixins de layout */
@use 'ng-hub-ui-ds' as hub;
.page { @include hub.center($max: xl); }
.toolbar { @include hub.cluster($gap: 2); }
.cards { @include hub.grid($min: 16rem, $gap: 3); }
/* Utilidades opt-in (canónicas hub- o sin prefijo) */
@use 'ng-hub-ui-ds/styles/utilities/layout.hub'; // .hub-stack .hub-gap-3 .hub-w-50 .hub-vh-100
@use 'ng-hub-ui-ds/styles/utilities/layout'; // .stack .gap-3 .w-auto .vw-100 (sin prefijo)Mixins de layout
Helpers Sass que consumen los tokens estructurales — sin hornear spacing ni color. Se importan namespaced con @use 'ng-hub-ui-ds' as hub. Cada demo de abajo está construida desde el mixin real.
Cada mixin tiene una utilidad equivalente; las demos de abajo consumen la clase real del ds (.hub-cluster, .hub-stack…) — esta página no re-aplica ningún mixin.
hub.cluster() · .hub-cluster — fila que envuelve
hub.stack() · .hub-stack — columna
hub.grid() · .hub-grid — grid auto-fit
hub.center() · .hub-center — wrapper centrado
@use 'ng-hub-ui-ds' as hub;
.toolbar { @include hub.cluster($gap: 2); } // fila que envuelve
.feed { @include hub.stack($gap: 3); } // columna
.cards { @include hub.grid($min: 8rem, $gap: 2); } // grid auto-fit
.page { @include hub.center($max: sm); } // wrapper centradoUtilidades
Clases opt-in que envuelven la misma capa. Dos sabores con idéntica regla de nombrado: canónicas con prefijo hub- (seguras, sin colisiones) o sin prefijo (.stack, .w-auto, .vh-100, .min-vh-100…) estilo framework. La demo usa las clases hub- reales:
.hub-cluster .hub-gap-2
.hub-grid .hub-gap-2
Sizing · .hub-w-50 · .hub-w-25 · .hub-w-auto
// importa la hoja una vez (canónica con prefijo hub- …)
@use 'ng-hub-ui-ds/styles/utilities/layout.hub';
// … o sin prefijo, estilo framework:
@use 'ng-hub-ui-ds/styles/utilities/layout';
<div class="hub-cluster hub-gap-2"> … </div>
<div class="hub-grid hub-gap-2"> … </div>
<div class="hub-w-50">mitad</div>
<div class="hub-vh-100 hub-min-vh-100">alto de viewport</div>Flexbox
Set completo de utilidades de display y flexbox (40 clases), simétrico en ambas hojas (hub- y sin prefijo). Las demos usan las clases reales del ds.
justify-content · .hub-justify-* — eje principal
.hub-justify-startalign-items · .hub-items-* — eje cruzado
.hub-items-startflex-direction · .hub-flex-column
flex-1 / flex-none — crecer y fijar
<!-- display + dirección / wrap -->
<div class="hub-d-flex hub-flex-wrap hub-gap-2"> … </div>
<div class="hub-d-flex hub-flex-column"> … </div>
<!-- eje principal (justify) y cruzado (items) -->
<div class="hub-d-flex hub-justify-between hub-items-center"> … </div>
<!-- crecer / fijar -->
<div class="hub-d-flex hub-gap-2">
<span class="hub-flex-1">crece</span>
<span class="hub-flex-none">fijo</span>
</div>Columnas, anchos y spacing
Rejilla de 12 columnas (.hub-row + .hub-col-1…12, driven por --hub-sys-grid-columns), anchos y padding/margin direccionales. Cada demo usa las utilidades reales.
Columnas · .hub-row + .hub-col-N
Anchos · .hub-w-25 / 50 / 75 / 100 / auto
Padding · .hub-p-1…5 (los 4 lados)
Padding por eje · .hub-px-* / .hub-py-*
Margin · .hub-m-1…5 (dentro de un marco de referencia)
Margin por eje · .hub-mx-* / .hub-my-*
<!-- 12-column grid: cada fila suma 12 -->
<div class="hub-row">
<div class="hub-col-6">col-6</div>
<div class="hub-col-6">col-6</div>
</div>
<div class="hub-row">
<div class="hub-col-4">col-4</div>
<div class="hub-col-4">col-4</div>
<div class="hub-col-4">col-4</div>
</div>
<!-- anchos · padding · margin direccionales -->
<div class="hub-w-50">w-50</div>
<div class="hub-p-3">padding 1rem en los 4 lados</div>
<div class="hub-px-4 hub-py-2">padding-inline 1.5rem · padding-block .5rem</div>
<div class="hub-mx-3">margin-inline 1rem</div>Puentes a otros sistemas
Mixins opt-in que conectan hub con el framework presente. Coste cero si no los llamas. Dos direcciones con $mode: adopt (hub toma el tema del host) y project (hub proyecta su tema sobre el host).
@use 'ng-hub-ui-ds' as hub;
/* "tengo Bootstrap y quiero que hub adopte su paleta" */
:root { @include hub.bridge-bootstrap($mode: adopt); }
/* "quiero teñir Material y Tailwind con MI tema hub" */
:root { @include hub.bridge-material($mode: project); }
:root { @include hub.bridge-tailwind($mode: project); }| Mixin | Sistema | adopt | project |
|---|---|---|---|
hub.bridge-bootstrap | Bootstrap 5.3+ | lee --bs-* | tiñe --bs-* + gutters/radius |
hub.bridge-material | Angular Material 3 | lee --mat-sys-* | tiñe --mat-sys-* (par color/on) |
hub.bridge-tailwind | Tailwind v4 | lee --color-* | emite --color-* para @theme |
hub.bridge-open-props | Open Props | alias de rampas | — |
Referencia rápida
| Quiero… | Cómo |
|---|---|
| Usar la paleta | @use '…/hub-tokens' |
| Cambiar un color global | :root { --hub-sys-color-primary: … } |
| Añadir variantes propias | with ($hub-accents-extra: (brand: …)) |
| Texto con contraste | color: var(--hub-sys-color-primary-on) |
| Layout (mixin / utilidad) | @include hub.center() · .hub-stack |
| Puente a Bootstrap/Material | @include hub.bridge-bootstrap($mode: adopt) |
| Crear un tema | [data-theme='<nombre>'] { … } |