ng-hub-ui-ds 22.11.4 → 22.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -7
- package/README.es.md +96 -37
- package/README.md +94 -37
- package/docs/variables-css-library.en.md +2021 -1886
- package/package.json +16 -4
- package/styles/mixins/_helpers.scss +7 -5
- package/styles/tokens/hub-tokens.css +209 -90
- package/styles/tokens/hub-tokens.scss +73 -36
- package/styles/utilities/layout.css +9 -45
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,74 @@ All notable changes to `ng-hub-ui-ds` are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [22.12.0] - 2026-09-23
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **The `-emphasis` role is readable on a dark surface again.** Its lightness was capped at
|
|
13
|
+
`min(l, 0.45)`, a rule written for ink on paper, so on the dark theme it pushed every accent
|
|
14
|
+
down instead of up. The five accents `[data-theme='dark']` re-tints hid the damage; the four it
|
|
15
|
+
does not — `secondary`, `neutral`, `light`, `dark` — showed it. Measured over
|
|
16
|
+
`--hub-sys-surface-elevated` (`#1e1e1e`): `neutral-emphasis` 2.25:1 → **6.74:1**,
|
|
17
|
+
`secondary-emphasis` 2.25:1 → **6.74:1**, `light-emphasis` 2.24:1 → **7.06:1** (via `#f8f9fa`),
|
|
18
|
+
`dark-emphasis` 1.08:1 → **6.73:1**. The five re-tinted accents were failing too —
|
|
19
|
+
`primary-emphasis` 2.21:1, `danger-emphasis` 2.10:1, `info-emphasis` 2.32:1 — and now read
|
|
20
|
+
6.90:1, 6.59:1 and 10.76:1. The `terminal` theme had the same nine failures, floor 2.26:1, and
|
|
21
|
+
now bottoms out at 6.89:1. Nothing changes on the light themes: their emphasis values are
|
|
22
|
+
byte-identical.
|
|
23
|
+
- **The focus ring is an indicator rather than a wash.** `rgba(13, 110, 253, 0.25)` composited
|
|
24
|
+
over the page at 1.41:1 where WCAG 1.4.11 asks 3:1, and the per-theme overrides were worse —
|
|
25
|
+
`sunset` 1.28:1, `mono` 1.41:1, `terminal` 2.89:1, `dark` 1.97:1. The ring is now the opaque
|
|
26
|
+
`--hub-sys-color-primary-emphasis` and measures 6.35:1 at its worst across the seven built-ins
|
|
27
|
+
(`forest`), 14.05:1 at its best (`mono`). Width drops from `0.25rem` to `0.125rem` so an opaque
|
|
28
|
+
ring does not read as a slab; 2px is the thickness WCAG 2.2 treats as the floor.
|
|
29
|
+
- **Links clear 4.5:1 on both surfaces of every theme.** `--hub-sys-link-color` was the raw
|
|
30
|
+
primary — 4.50:1 on `#ffffff` but **4.27:1** on `#f8f9fa`, so a link inside a card failed — and
|
|
31
|
+
`--hub-sys-link-hover-color` was a hard-coded `#0a58ca`, a blue that meant nothing in an orange
|
|
32
|
+
or a green theme. Both derive now: the link from `--hub-sys-color-primary-emphasis`, the hover
|
|
33
|
+
by walking that colour toward `--hub-sys-color-ink`, which darkens on a light theme and lightens
|
|
34
|
+
on a dark one. Worst link in the package is now 6.35:1 (`forest`), worst hover 7.47:1. The
|
|
35
|
+
`sunset` literal that cleared the bar by two hundredths (4.52:1) is gone with them.
|
|
36
|
+
- **`.focus-ring-{variant}` re-tints the ring opaquely.** The `focus-ring-color()` mixin mixed the
|
|
37
|
+
accent to 25% alpha, which put every one of those utilities near 1.3:1. It now reads the
|
|
38
|
+
variant's `-emphasis` role.
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- **`--hub-sys-border-color-strong`** — the boundary of an interactive control, which 1.4.11 wants
|
|
43
|
+
at 3:1. `--hub-sys-border-color-default` is the decorative hairline and measures 1.30:1 on white,
|
|
44
|
+
so a control drawn with it has no visible edge. Derived from the theme's own ink and surface, so
|
|
45
|
+
it needs no per-theme literal: 5.21:1 on the light themes, 3.42:1 at its tightest (`sunset`).
|
|
46
|
+
- **`--hub-sys-emphasis-lightness-min` / `--hub-sys-emphasis-lightness-max`** — the lightness
|
|
47
|
+
window the `-emphasis` role is steered into, `0`/`0.45` on a light theme and `0.72`/`1` on
|
|
48
|
+
`dark` and `terminal`. A custom dark theme sets these two and every accent in the open map,
|
|
49
|
+
including ones the consumer added, comes out readable.
|
|
50
|
+
- **`npm run check:contrast`** (`scripts/check-contrast.mjs`) — measures every accent, link, focus
|
|
51
|
+
ring and control border of the compiled sheet against both surfaces of every theme it finds, and
|
|
52
|
+
exits non-zero if a shipped default drops under its threshold. Themes and accents are discovered
|
|
53
|
+
from the CSS, so a new one is covered without touching the script. It runs on `prepublishOnly`.
|
|
54
|
+
|
|
55
|
+
### Changed
|
|
56
|
+
|
|
57
|
+
- The `bootstrap`, `dark`, `sunset`, `forest` and `mono` themes no longer carry their own
|
|
58
|
+
`--hub-sys-link-color` / `--hub-sys-link-hover-color`, and none of the six themes carries its own
|
|
59
|
+
`--hub-sys-focus-ring-color`. What derives in their place is the same colour or a better one —
|
|
60
|
+
for `dark` it resolves to the very `#6ea8fe` the block used to spell out. `terminal` keeps its
|
|
61
|
+
cyan links, which are deliberate and measure 11.75:1.
|
|
62
|
+
|
|
63
|
+
### Removed
|
|
64
|
+
|
|
65
|
+
- `--hub-focus-ring-opacity`. It existed to thin the ring, which is the defect.
|
|
66
|
+
|
|
67
|
+
## [22.11.5] - 2026-09-20
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
|
|
71
|
+
- The npm keywords say that this package is the token layer — `tokens`, `css-custom-properties`,
|
|
72
|
+
`theming`, `themes`, `color-palette`, `spacing`, `typography` — and that it is
|
|
73
|
+
`framework-agnostic`, which is the reason somebody outside Angular would install it at all.
|
|
74
|
+
Metadata only: no token, variable or style changes.
|
|
75
|
+
|
|
8
76
|
## [22.11.4] - 2026-09-16
|
|
9
77
|
|
|
10
78
|
### Changed
|
|
@@ -55,14 +123,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
55
123
|
inherited unreadable text through `.text-warning-emphasis` and through any component
|
|
56
124
|
reading the role, and none of them could fix it, because the formula lives here.
|
|
57
125
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
126
|
+
The luminosity is capped instead of mixed — `oklch(from <accent> min(l, .45) c h)` —
|
|
127
|
+
which leaves an already-dark accent exactly where it was and pulls a light one down to
|
|
128
|
+
where it can carry a letter, keeping its hue and its chroma. Measured on white across the
|
|
129
|
+
nine defaults: nothing below 6.6:1 — info is the floor at 6.62, success next at 6.91 —
|
|
130
|
+
and no role moves by more than a point unless it was failing. `dark` is untouched, since
|
|
131
|
+
it already sat at L .26.
|
|
132
|
+
|
|
133
|
+
Themes that assign `--hub-sys-color-*-emphasis` by hand are unaffected.
|
|
64
134
|
|
|
65
|
-
Themes that assign `--hub-sys-color-*-emphasis` by hand are unaffected.
|
|
66
135
|
## [22.10.0] - 2026-09-08
|
|
67
136
|
|
|
68
137
|
### Added
|
package/README.es.md
CHANGED
|
@@ -145,11 +145,11 @@ propios estilos:
|
|
|
145
145
|
|
|
146
146
|
Los tokens siguen un sistema por capas:
|
|
147
147
|
|
|
148
|
-
| Capa
|
|
149
|
-
|
|
|
150
|
-
| **Referencia**
|
|
151
|
-
| **Sistema**
|
|
152
|
-
| **Container**
|
|
148
|
+
| Capa | Prefijo | Qué es | Ejemplos |
|
|
149
|
+
| ---------------- | -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
150
|
+
| **Referencia** | `--hub-ref-*` | Valores crudos, sin contexto | `--hub-ref-color-blue-500`, `--hub-ref-space-3`, `--hub-ref-radius-md` |
|
|
151
|
+
| **Sistema** | `--hub-sys-*` | Asignaciones con significado que consumen los componentes | `--hub-sys-color-primary`, `--hub-sys-surface-page`, `--hub-sys-text-primary` |
|
|
152
|
+
| **Container** | `--hub-container-*` | Puente heredable de `sys` a contenedores/slots concretos — un **re-base hook** | `--hub-container-bg`, `--hub-container-padding-x`, `--hub-container-gap` |
|
|
153
153
|
| **Base / shell** | `--hub-body-*` · `--hub-main-*` · `--hub-main-wrapper-*` | Layout del _application shell_: el wrapper exterior de la página, la región de contenido y su wrapper centrado. `--hub-body-*` **hereda los valores por defecto de `--hub-container-*`** | `--hub-body-padding-x`, `--hub-main-bg`, `--hub-main-wrapper-max-width` (`1200px`) |
|
|
154
154
|
|
|
155
155
|
Regla de oro: **los componentes referencian solo tokens `sys`**. Los `sys`
|
|
@@ -189,13 +189,13 @@ defecto es `primary` · `secondary` · `success` · `danger` · `warning` · `in
|
|
|
189
189
|
`light` · `dark`, y es **abierto**: cada variante que añadas obtiene la misma familia (ver
|
|
190
190
|
[Cómo modificarlo](#️-cómo-modificarlo)).
|
|
191
191
|
|
|
192
|
-
| Token | Uso típico
|
|
193
|
-
| ----------------------------------- |
|
|
194
|
-
| `--hub-sys-color-<v>` | Color sólido (acento, icono, borde fuerte)
|
|
195
|
-
| `--hub-sys-color-<v>-subtle` | Fondo tenue (banners, alertas)
|
|
196
|
-
| `--hub-sys-color-<v>-border-subtle` | Borde tenue sobre el fondo subtle
|
|
197
|
-
| `--hub-sys-color-<v>-emphasis` | Texto legible sobre el
|
|
198
|
-
| `--hub-sys-color-<v>-on` | Color de texto/icono con contraste **sobre** el acento
|
|
192
|
+
| Token | Uso típico |
|
|
193
|
+
| ----------------------------------- | --------------------------------------------------------------------------------- |
|
|
194
|
+
| `--hub-sys-color-<v>` | Color sólido (acento, icono, borde fuerte) |
|
|
195
|
+
| `--hub-sys-color-<v>-subtle` | Fondo tenue (banners, alertas) |
|
|
196
|
+
| `--hub-sys-color-<v>-border-subtle` | Borde tenue sobre el fondo subtle |
|
|
197
|
+
| `--hub-sys-color-<v>-emphasis` | Texto legible sobre la superficie — los enlaces y el halo de foco también lo leen |
|
|
198
|
+
| `--hub-sys-color-<v>-on` | Color de texto/icono con contraste **sobre** el acento |
|
|
199
199
|
|
|
200
200
|
Ejemplo de uso (un aviso a juego con el resto de la familia):
|
|
201
201
|
|
|
@@ -216,7 +216,7 @@ contenedor para tematizar una zona):
|
|
|
216
216
|
|
|
217
217
|
```html
|
|
218
218
|
<html data-theme="dark">
|
|
219
|
-
|
|
219
|
+
<!-- light (por defecto) · base · bootstrap · dark · sunset · forest · mono · terminal -->
|
|
220
220
|
</html>
|
|
221
221
|
```
|
|
222
222
|
|
|
@@ -232,9 +232,9 @@ Además de los tokens, el paquete incluye una capa de estilos opt-in — no se e
|
|
|
232
232
|
**Hojas de utilidades** — los nombres de clase son **exactamente los de Bootstrap** y cada valor resuelve a los tokens canónicos. No cargues estas hojas Y Bootstrap globalmente en el mismo documento. Cada hoja tiene además su gemela `.css` compilada para apps sin Sass:
|
|
233
233
|
|
|
234
234
|
```scss
|
|
235
|
-
@use 'ng-hub-ui-ds/styles/utilities/layout';
|
|
236
|
-
@use 'ng-hub-ui-ds/styles/utilities/text';
|
|
237
|
-
@use 'ng-hub-ui-ds/styles/utilities/surfaces';
|
|
235
|
+
@use 'ng-hub-ui-ds/styles/utilities/layout'; // display/flex (+ responsive), grid de 12 col + offsets, spacing, sizing, position, overflow, order, .vr, .ratio-*, .visually-hidden…
|
|
236
|
+
@use 'ng-hub-ui-ds/styles/utilities/text'; // .fs-1…6, .h1…6, .fw-*, .lh-*, .text-truncate, colores de texto semánticos
|
|
237
|
+
@use 'ng-hub-ui-ds/styles/utilities/surfaces'; // .bg-* (+ -subtle), .text-bg-*, .border*, .rounded*, .shadow*, .opacity-*
|
|
238
238
|
```
|
|
239
239
|
|
|
240
240
|
Los únicos nombres fuera de Bootstrap son los primitivos de layout que reflejan los mixins: `.stack`, `.cluster`, `.grid-auto`, `.center`.
|
|
@@ -250,10 +250,21 @@ Los únicos nombres fuera de Bootstrap son los primitivos de layout que reflejan
|
|
|
250
250
|
```scss
|
|
251
251
|
@use 'ng-hub-ui-ds' as hub;
|
|
252
252
|
|
|
253
|
-
.toolbar
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
.
|
|
253
|
+
.toolbar {
|
|
254
|
+
@include hub.cluster($gap: 2);
|
|
255
|
+
}
|
|
256
|
+
.card__title {
|
|
257
|
+
@include hub.font-size(4);
|
|
258
|
+
@include hub.font-weight(semibold);
|
|
259
|
+
}
|
|
260
|
+
.card--brand {
|
|
261
|
+
@include hub.text-bg(brand);
|
|
262
|
+
@include hub.radius(lg);
|
|
263
|
+
@include hub.shadow(sm);
|
|
264
|
+
}
|
|
265
|
+
.sr-label {
|
|
266
|
+
@include hub.visually-hidden();
|
|
267
|
+
}
|
|
257
268
|
```
|
|
258
269
|
|
|
259
270
|
Grupos: **tema** (`theme()` — tematización parcial en una llamada: pásale solo las escalas/acentos cambiados como mapas), **breakpoints** (`media-breakpoint-up/down` sobre el mapa `$hub-breakpoints` — de él se generan las variantes responsive `.d-md-*`, `.col-lg-*`, `.p-sm-*`…), **layout** (`stack`, `cluster`, `grid`, `grid-fixed`, `row`, `col`, `offset`, `center`), **tipografía** (`font-family`, `font-size`, `font-weight`, `line-height`, `text-color`, `link-color`, `text-truncate`, `text-break`), **superficies** (`bg`, `text-bg`, `border`, `border-color`, `radius`, `shadow`), **helpers** (`focus-ring`, `focus-ring-color`, `visually-hidden`, `stretched-link`, `ratio`, `clearfix`) y los **puentes** (`bridge-bootstrap` / `bridge-material` / `bridge-tailwind` / `bridge-open-props`).
|
|
@@ -331,12 +342,12 @@ $hub-accents: (
|
|
|
331
342
|
primary: var(--hub-ref-color-blue-500, #0d6efd),
|
|
332
343
|
secondary: var(--hub-ref-color-gray-600, #6c757d),
|
|
333
344
|
success: var(--hub-ref-color-green-500, #198754),
|
|
334
|
-
danger:
|
|
345
|
+
danger: var(--hub-ref-color-red-500, #dc3545),
|
|
335
346
|
warning: var(--hub-ref-color-yellow-500, #ffc107),
|
|
336
|
-
info:
|
|
347
|
+
info: var(--hub-ref-color-cyan-500, #0dcaf0),
|
|
337
348
|
neutral: var(--hub-ref-color-gray-600, #6c757d),
|
|
338
|
-
light:
|
|
339
|
-
dark:
|
|
349
|
+
light: var(--hub-ref-color-gray-100, #f8f9fa),
|
|
350
|
+
dark: var(--hub-ref-color-gray-900, #212529)
|
|
340
351
|
) !default;
|
|
341
352
|
|
|
342
353
|
// Override aditivo — pasa SOLO las variantes que añades o retocas, conserva las demás.
|
|
@@ -356,12 +367,29 @@ $hub-accents: map.merge($hub-accents, $hub-accents-extra);
|
|
|
356
367
|
// obtiene su familia completa gratis.
|
|
357
368
|
@mixin hub-color-derive() {
|
|
358
369
|
@each $name in map.keys($hub-accents) {
|
|
359
|
-
--hub-sys-color-#{$name}-subtle:
|
|
360
|
-
|
|
361
|
-
|
|
370
|
+
--hub-sys-color-#{$name}-subtle: color-mix(
|
|
371
|
+
in oklch,
|
|
372
|
+
var(--hub-sys-color-#{$name}) 12%,
|
|
373
|
+
var(--hub-sys-surface-page, #fff)
|
|
374
|
+
);
|
|
375
|
+
--hub-sys-color-#{$name}-border-subtle: color-mix(
|
|
376
|
+
in oklch,
|
|
377
|
+
var(--hub-sys-color-#{$name}) 35%,
|
|
378
|
+
var(--hub-sys-surface-page, #fff)
|
|
379
|
+
);
|
|
380
|
+
// La luminosidad se lleva a la ventana que fija el tema — 0…0,45 en un tema claro,
|
|
381
|
+
// 0,72…1 en uno oscuro — para que el texto de énfasis siga leyéndose vaya la
|
|
382
|
+
// superficie hacia donde vaya. Una mezcla por porcentaje no puede: nunca oscurece
|
|
383
|
+
// un tono pálido.
|
|
384
|
+
--hub-sys-color-#{$name}-emphasis: oklch(
|
|
385
|
+
from var(--hub-sys-color-#{$name})
|
|
386
|
+
clamp(var(--hub-sys-emphasis-lightness-min, 0), l, var(--hub-sys-emphasis-lightness-max, 1))
|
|
387
|
+
c
|
|
388
|
+
h
|
|
389
|
+
);
|
|
362
390
|
// Volteo de contraste en escala de grises según la luminosidad del propio acento:
|
|
363
391
|
// los acentos oscuros (L < .62) resuelven a texto blanco; los claros, a casi negro.
|
|
364
|
-
--hub-sys-color-#{$name}-on:
|
|
392
|
+
--hub-sys-color-#{$name}-on: oklch(from var(--hub-sys-color-#{$name}) clamp(0, (0.62 - l) * 1000, 1) 0 h);
|
|
365
393
|
}
|
|
366
394
|
}
|
|
367
395
|
|
|
@@ -378,18 +406,41 @@ $hub-accents: map.merge($hub-accents, $hub-accents-extra);
|
|
|
378
406
|
> `-emphasis` / `-on` automáticamente. Los mapas + mixins son solo la mecánica
|
|
379
407
|
> interna, útil si contribuyes al paquete o compilas tu propia variante de la paleta.
|
|
380
408
|
|
|
409
|
+
### Escribir un tema oscuro propio
|
|
410
|
+
|
|
411
|
+
Fija la ventana de énfasis junto con las superficies, o cada acento se irá hacia el lado
|
|
412
|
+
equivocado:
|
|
413
|
+
|
|
414
|
+
```css
|
|
415
|
+
[data-theme='midnight'] {
|
|
416
|
+
--hub-sys-surface-page: #0b0d10;
|
|
417
|
+
--hub-sys-surface-elevated: #14181d;
|
|
418
|
+
--hub-sys-text-primary: #eef1f5;
|
|
419
|
+
--hub-sys-color-ink: #eef1f5;
|
|
420
|
+
/* Sin estas dos, `-emphasis` oscurece en vez de aclarar y un botón ghost sobre
|
|
421
|
+
esta superficie se queda alrededor de 2:1. */
|
|
422
|
+
--hub-sys-emphasis-lightness-min: 0.72;
|
|
423
|
+
--hub-sys-emphasis-lightness-max: 1;
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Los enlaces, el halo de foco y `--hub-sys-border-color-strong` salen de ahí, así que no hay nada
|
|
428
|
+
más que declarar. Comprueba el resultado con `npm run check:contrast`, que mide cada acento,
|
|
429
|
+
enlace, halo y borde de control de la hoja compilada contra las dos superficies de cada tema que
|
|
430
|
+
encuentra, y falla si alguno baja de su umbral WCAG.
|
|
431
|
+
|
|
381
432
|
---
|
|
382
433
|
|
|
383
434
|
## 📋 Tabla de referencia rápida
|
|
384
435
|
|
|
385
|
-
| Quiero…
|
|
386
|
-
|
|
|
387
|
-
| Usar la paleta
|
|
388
|
-
| Cambiar un color global
|
|
389
|
-
| Cambiar el modo oscuro
|
|
390
|
-
| Añadir un acento propio
|
|
391
|
-
| Crear un tema
|
|
392
|
-
| Ver todos los tokens
|
|
436
|
+
| Quiero… | Cómo |
|
|
437
|
+
| ----------------------- | ----------------------------------------------------------------------- |
|
|
438
|
+
| Usar la paleta | `@import '…/hub-tokens.css'` una vez |
|
|
439
|
+
| Cambiar un color global | `:root { --hub-sys-color-primary: … }` |
|
|
440
|
+
| Cambiar el modo oscuro | `[data-theme='dark'] { --hub-sys-… : … }` |
|
|
441
|
+
| Añadir un acento propio | define `--hub-sys-color-<x>` (+ familia opcional) |
|
|
442
|
+
| Crear un tema | `[data-theme='<nombre>'] { … }` y actívalo |
|
|
443
|
+
| Ver todos los tokens | la página de tokens en [hubui.dev](https://hubui.dev/en/design-system/) |
|
|
393
444
|
|
|
394
445
|
---
|
|
395
446
|
|
|
@@ -414,9 +465,17 @@ Repositorio: https://github.com/hub-env/ng-hub-ui-ds
|
|
|
414
465
|
¿Te gusta este paquete? Puedes apoyar el proyecto invitándome a un café ☕:
|
|
415
466
|
[](https://buymeacoffee.com/carlosmorcillo)
|
|
416
467
|
|
|
468
|
+
## 💼 Soporte comercial
|
|
469
|
+
|
|
470
|
+
Mantengo estas librerías yo mismo: soy [Carlos Morcillo Fernández](https://www.carlosmorcillo.com), arquitecto frontend autónomo, y trabajo con equipos que construyen y mantienen aplicaciones Angular.
|
|
471
|
+
|
|
472
|
+
Si tu equipo depende de Hub-UI y necesita más de lo que se resuelve en un hilo de incidencias, eso es a lo que me dedico: auditorías de arquitectura, sistemas de diseño, migraciones de Angular y mentoría de equipos. Cuando el proyecto pide además diseño y un equipo completo, lo llevo por [Frog Hub](https://froghub.es), mi estudio de desarrollo.
|
|
473
|
+
|
|
474
|
+
Aquí están [los servicios](https://www.carlosmorcillo.com/servicios/) y aquí puedes [contarme tu proyecto](https://www.carlosmorcillo.com/contacto/).
|
|
475
|
+
|
|
417
476
|
## 📄 Licencia
|
|
418
477
|
|
|
419
478
|
Este proyecto está licenciado bajo la Licencia MIT.
|
|
420
479
|
|
|
421
|
-
MIT © [Carlos Morcillo](https://www.carlosmorcillo.com)
|
|
480
|
+
MIT © [Carlos Morcillo Fernández](https://www.carlosmorcillo.com)
|
|
422
481
|
</content>
|
package/README.md
CHANGED
|
@@ -146,11 +146,11 @@ own styles too:
|
|
|
146
146
|
|
|
147
147
|
The tokens follow a layered system:
|
|
148
148
|
|
|
149
|
-
| Layer
|
|
150
|
-
|
|
|
151
|
-
| **Reference**
|
|
152
|
-
| **System**
|
|
153
|
-
| **Container**
|
|
149
|
+
| Layer | Prefix | What it is | Examples |
|
|
150
|
+
| ---------------- | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
151
|
+
| **Reference** | `--hub-ref-*` | Raw, context-free values | `--hub-ref-color-blue-500`, `--hub-ref-space-3`, `--hub-ref-radius-md` |
|
|
152
|
+
| **System** | `--hub-sys-*` | Meaningful assignments that components consume | `--hub-sys-color-primary`, `--hub-sys-surface-page`, `--hub-sys-text-primary` |
|
|
153
|
+
| **Container** | `--hub-container-*` | Inheritable bridge from `sys` to concrete containers/slots — a **re-base hook** | `--hub-container-bg`, `--hub-container-padding-x`, `--hub-container-gap` |
|
|
154
154
|
| **Base / shell** | `--hub-body-*` · `--hub-main-*` · `--hub-main-wrapper-*` | Application-shell layout: the outer page wrapper, the content region and its centered wrapper. `--hub-body-*` **inherits the matching `--hub-container-*` defaults** | `--hub-body-padding-x`, `--hub-main-bg`, `--hub-main-wrapper-max-width` (`1200px`) |
|
|
155
155
|
|
|
156
156
|
Golden rule: **components reference `sys` tokens only**. The `sys` tokens point
|
|
@@ -190,13 +190,13 @@ Each semantic variant exposes a **uniform family** of five tokens. The default s
|
|
|
190
190
|
`dark`, and it is **open**: every variant you add gets the same family (see
|
|
191
191
|
[How to customise it](#️-how-to-customise-it)).
|
|
192
192
|
|
|
193
|
-
| Token | Typical use
|
|
194
|
-
| ----------------------------------- |
|
|
195
|
-
| `--hub-sys-color-<v>` | Solid colour (accent, icon, strong border)
|
|
196
|
-
| `--hub-sys-color-<v>-subtle` | Faint background (banners, alerts)
|
|
197
|
-
| `--hub-sys-color-<v>-border-subtle` | Faint border over the subtle background
|
|
198
|
-
| `--hub-sys-color-<v>-emphasis` | Legible text over the
|
|
199
|
-
| `--hub-sys-color-<v>-on` | Contrast text/icon colour laid **on** the accent
|
|
193
|
+
| Token | Typical use |
|
|
194
|
+
| ----------------------------------- | ----------------------------------------------------------------- |
|
|
195
|
+
| `--hub-sys-color-<v>` | Solid colour (accent, icon, strong border) |
|
|
196
|
+
| `--hub-sys-color-<v>-subtle` | Faint background (banners, alerts) |
|
|
197
|
+
| `--hub-sys-color-<v>-border-subtle` | Faint border over the subtle background |
|
|
198
|
+
| `--hub-sys-color-<v>-emphasis` | Legible text over the surface — links and focus rings read it too |
|
|
199
|
+
| `--hub-sys-color-<v>-on` | Contrast text/icon colour laid **on** the accent |
|
|
200
200
|
|
|
201
201
|
Usage example (a callout that matches the rest of the family):
|
|
202
202
|
|
|
@@ -217,7 +217,7 @@ container to theme a region):
|
|
|
217
217
|
|
|
218
218
|
```html
|
|
219
219
|
<html data-theme="dark">
|
|
220
|
-
|
|
220
|
+
<!-- light (default) · base · bootstrap · dark · sunset · forest · mono · terminal -->
|
|
221
221
|
</html>
|
|
222
222
|
```
|
|
223
223
|
|
|
@@ -234,9 +234,9 @@ Besides the tokens, the package ships an opt-in styling layer — nothing is emi
|
|
|
234
234
|
**Utility sheets** — class names mirror Bootstrap's **exactly** and every value resolves to the canonical tokens. Do not load them AND Bootstrap globally in the same document. Each sheet also has a compiled `.css` twin for Sass-less apps:
|
|
235
235
|
|
|
236
236
|
```scss
|
|
237
|
-
@use 'ng-hub-ui-ds/styles/utilities/layout';
|
|
238
|
-
@use 'ng-hub-ui-ds/styles/utilities/text';
|
|
239
|
-
@use 'ng-hub-ui-ds/styles/utilities/surfaces';
|
|
237
|
+
@use 'ng-hub-ui-ds/styles/utilities/layout'; // display/flex (+ responsive), 12-col grid + offsets, spacing, sizing, position, overflow, order, .vr, .ratio-*, .visually-hidden…
|
|
238
|
+
@use 'ng-hub-ui-ds/styles/utilities/text'; // .fs-1…6, .h1…6, .fw-*, .lh-*, .text-truncate, semantic text colours
|
|
239
|
+
@use 'ng-hub-ui-ds/styles/utilities/surfaces'; // .bg-* (+ -subtle), .text-bg-*, .border*, .rounded*, .shadow*, .opacity-*
|
|
240
240
|
```
|
|
241
241
|
|
|
242
242
|
The only non-Bootstrap names are the layout primitives that mirror the mixins: `.stack`, `.cluster`, `.grid-auto`, `.center`.
|
|
@@ -252,10 +252,21 @@ The only non-Bootstrap names are the layout primitives that mirror the mixins: `
|
|
|
252
252
|
```scss
|
|
253
253
|
@use 'ng-hub-ui-ds' as hub;
|
|
254
254
|
|
|
255
|
-
.toolbar
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
.
|
|
255
|
+
.toolbar {
|
|
256
|
+
@include hub.cluster($gap: 2);
|
|
257
|
+
}
|
|
258
|
+
.card__title {
|
|
259
|
+
@include hub.font-size(4);
|
|
260
|
+
@include hub.font-weight(semibold);
|
|
261
|
+
}
|
|
262
|
+
.card--brand {
|
|
263
|
+
@include hub.text-bg(brand);
|
|
264
|
+
@include hub.radius(lg);
|
|
265
|
+
@include hub.shadow(sm);
|
|
266
|
+
}
|
|
267
|
+
.sr-label {
|
|
268
|
+
@include hub.visually-hidden();
|
|
269
|
+
}
|
|
259
270
|
```
|
|
260
271
|
|
|
261
272
|
Groups: **theme** (`theme()` — partial theming in one call: pass only the changed scales/accents as maps), **breakpoints** (`media-breakpoint-up/down` over the `$hub-breakpoints` map — the responsive variants `.d-md-*`, `.col-lg-*`, `.p-sm-*`… are generated from it), **layout** (`stack`, `cluster`, `grid`, `grid-fixed`, `row`, `col`, `offset`, `center`), **typography** (`font-family`, `font-size`, `font-weight`, `line-height`, `text-color`, `link-color`, `text-truncate`, `text-break`), **surfaces** (`bg`, `text-bg`, `border`, `border-color`, `radius`, `shadow`), **helpers** (`focus-ring`, `focus-ring-color`, `visually-hidden`, `stretched-link`, `ratio`, `clearfix`) and the **bridges** (`bridge-bootstrap` / `bridge-material` / `bridge-tailwind` / `bridge-open-props`).
|
|
@@ -333,12 +344,12 @@ $hub-accents: (
|
|
|
333
344
|
primary: var(--hub-ref-color-blue-500, #0d6efd),
|
|
334
345
|
secondary: var(--hub-ref-color-gray-600, #6c757d),
|
|
335
346
|
success: var(--hub-ref-color-green-500, #198754),
|
|
336
|
-
danger:
|
|
347
|
+
danger: var(--hub-ref-color-red-500, #dc3545),
|
|
337
348
|
warning: var(--hub-ref-color-yellow-500, #ffc107),
|
|
338
|
-
info:
|
|
349
|
+
info: var(--hub-ref-color-cyan-500, #0dcaf0),
|
|
339
350
|
neutral: var(--hub-ref-color-gray-600, #6c757d),
|
|
340
|
-
light:
|
|
341
|
-
dark:
|
|
351
|
+
light: var(--hub-ref-color-gray-100, #f8f9fa),
|
|
352
|
+
dark: var(--hub-ref-color-gray-900, #212529)
|
|
342
353
|
) !default;
|
|
343
354
|
|
|
344
355
|
// Additive override — pass ONLY the variants you add or retune, keep the defaults.
|
|
@@ -358,12 +369,28 @@ $hub-accents: map.merge($hub-accents, $hub-accents-extra);
|
|
|
358
369
|
// its full family for free.
|
|
359
370
|
@mixin hub-color-derive() {
|
|
360
371
|
@each $name in map.keys($hub-accents) {
|
|
361
|
-
--hub-sys-color-#{$name}-subtle:
|
|
362
|
-
|
|
363
|
-
|
|
372
|
+
--hub-sys-color-#{$name}-subtle: color-mix(
|
|
373
|
+
in oklch,
|
|
374
|
+
var(--hub-sys-color-#{$name}) 12%,
|
|
375
|
+
var(--hub-sys-surface-page, #fff)
|
|
376
|
+
);
|
|
377
|
+
--hub-sys-color-#{$name}-border-subtle: color-mix(
|
|
378
|
+
in oklch,
|
|
379
|
+
var(--hub-sys-color-#{$name}) 35%,
|
|
380
|
+
var(--hub-sys-surface-page, #fff)
|
|
381
|
+
);
|
|
382
|
+
// Lightness steered into the window the theme owns — 0…0.45 on a light theme,
|
|
383
|
+
// 0.72…1 on a dark one — so emphasis text stays readable whichever way the
|
|
384
|
+
// surface goes. A percentage mix cannot do this: it never darkens a pale hue.
|
|
385
|
+
--hub-sys-color-#{$name}-emphasis: oklch(
|
|
386
|
+
from var(--hub-sys-color-#{$name})
|
|
387
|
+
clamp(var(--hub-sys-emphasis-lightness-min, 0), l, var(--hub-sys-emphasis-lightness-max, 1))
|
|
388
|
+
c
|
|
389
|
+
h
|
|
390
|
+
);
|
|
364
391
|
// Grayscale contrast flip driven by the accent's own lightness: dark accents
|
|
365
392
|
// (L < .62) resolve to white text, light accents to near-black.
|
|
366
|
-
--hub-sys-color-#{$name}-on:
|
|
393
|
+
--hub-sys-color-#{$name}-on: oklch(from var(--hub-sys-color-#{$name}) clamp(0, (0.62 - l) * 1000, 1) 0 h);
|
|
367
394
|
}
|
|
368
395
|
}
|
|
369
396
|
|
|
@@ -380,18 +407,40 @@ $hub-accents: map.merge($hub-accents, $hub-accents-extra);
|
|
|
380
407
|
> `-on` automatically. The maps + mixins are just the internal mechanism, useful if
|
|
381
408
|
> you contribute to the package or compile your own palette variant.
|
|
382
409
|
|
|
410
|
+
### Writing a dark theme of your own
|
|
411
|
+
|
|
412
|
+
Set the emphasis window along with the surfaces, or every accent gets pushed the wrong way:
|
|
413
|
+
|
|
414
|
+
```css
|
|
415
|
+
[data-theme='midnight'] {
|
|
416
|
+
--hub-sys-surface-page: #0b0d10;
|
|
417
|
+
--hub-sys-surface-elevated: #14181d;
|
|
418
|
+
--hub-sys-text-primary: #eef1f5;
|
|
419
|
+
--hub-sys-color-ink: #eef1f5;
|
|
420
|
+
/* Without these two, `-emphasis` darkens instead of lightening and a ghost
|
|
421
|
+
button on this surface lands around 2:1. */
|
|
422
|
+
--hub-sys-emphasis-lightness-min: 0.72;
|
|
423
|
+
--hub-sys-emphasis-lightness-max: 1;
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Links, the focus ring and `--hub-sys-border-color-strong` all follow from those, so there is
|
|
428
|
+
nothing else to declare. Check the result with `npm run check:contrast`, which measures every
|
|
429
|
+
accent, link, ring and control border of the compiled sheet against both surfaces of every theme
|
|
430
|
+
it finds and fails if one drops below its WCAG threshold.
|
|
431
|
+
|
|
383
432
|
---
|
|
384
433
|
|
|
385
434
|
## 📋 Quick reference table
|
|
386
435
|
|
|
387
|
-
| I want to…
|
|
388
|
-
|
|
|
389
|
-
| Use the palette
|
|
390
|
-
| Change a global colour
|
|
391
|
-
| Change dark mode
|
|
392
|
-
| Add your own accent
|
|
393
|
-
| Create a theme
|
|
394
|
-
| See all the tokens
|
|
436
|
+
| I want to… | How |
|
|
437
|
+
| ---------------------- | ------------------------------------------------------------------- |
|
|
438
|
+
| Use the palette | `@import '…/hub-tokens.css'` once |
|
|
439
|
+
| Change a global colour | `:root { --hub-sys-color-primary: … }` |
|
|
440
|
+
| Change dark mode | `[data-theme='dark'] { --hub-sys-… : … }` |
|
|
441
|
+
| Add your own accent | define `--hub-sys-color-<x>` (+ optional family) |
|
|
442
|
+
| Create a theme | `[data-theme='<name>'] { … }` and activate it |
|
|
443
|
+
| See all the tokens | the tokens page at [hubui.dev](https://hubui.dev/en/design-system/) |
|
|
395
444
|
|
|
396
445
|
---
|
|
397
446
|
|
|
@@ -416,10 +465,18 @@ Repository: https://github.com/hub-env/ng-hub-ui-ds
|
|
|
416
465
|
Do you like this package? You can support the project by buying a coffee ☕:
|
|
417
466
|
[](https://buymeacoffee.com/carlosmorcillo)
|
|
418
467
|
|
|
468
|
+
## 💼 Commercial support
|
|
469
|
+
|
|
470
|
+
These libraries are maintained by [Carlos Morcillo Fernández](https://www.carlosmorcillo.com), a freelance frontend architect working with teams that build and maintain Angular applications.
|
|
471
|
+
|
|
472
|
+
If your team depends on Hub-UI and needs more than an issue thread can solve, that is my day job: architecture audits, design systems, Angular migrations and team mentoring. For projects that also need design and a full team, I run them through [Frog Hub](https://froghub.es), my development studio.
|
|
473
|
+
|
|
474
|
+
Have a look at [the services](https://www.carlosmorcillo.com/en/services/) or [tell me about your project](https://www.carlosmorcillo.com/en/contact/).
|
|
475
|
+
|
|
419
476
|
## 📄 License
|
|
420
477
|
|
|
421
478
|
This project is licensed under the MIT License.
|
|
422
479
|
|
|
423
|
-
MIT © [Carlos Morcillo](https://www.carlosmorcillo.com)
|
|
480
|
+
MIT © [Carlos Morcillo Fernández](https://www.carlosmorcillo.com)
|
|
424
481
|
</content>
|
|
425
482
|
</invoke>
|