ng-hub-ui-ds 22.5.6 → 22.6.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 CHANGED
@@ -5,6 +5,23 @@ 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.6.0] - 2026-07-09
9
+
10
+ ### Added
11
+
12
+ - **utilities — the Bootstrap-standard classes the sheets were missing.** The utility sheets promise Bootstrap-exact names; an audit against `bootstrap@5` found 74 base classes documented there but absent here. All of them now ship, emitted through the existing accent loops and the surface/typography mixins, so they follow a re-theme like everything else:
13
+ - `text.scss` — `.text-{accent}-emphasis` (the accent driven toward the theme's ink; legible as body copy on its own `-subtle` background), `.text-black-50` / `.text-white-50`, `.link-opacity-{10,25,50,75,100}`.
14
+ - `surfaces.scss` — `.bg-body-secondary` / `.bg-body-tertiary` (the **surface** de-emphasis ramp), `.border-{accent}-subtle`, `.border-black` / `.border-white`, `.border-opacity-{10,25,50,75,100}`, and the side-scoped radii `.rounded-{top,bottom,start,end}-{0..5,circle,pill}` — logical corners, so they flip correctly in RTL.
15
+ - `layout.scss` — `.d-inline-grid` (plus its `.d-print-` and responsive variants), `.focus-ring-{accent}`.
16
+ - **tokens — `--hub-sys-text-secondary` and `--hub-sys-text-tertiary`.** Two rungs of the text de-emphasis ramp were consumed by `text-color()` through a fallback but never declared, so `.text-body-secondary` and `.text-body-tertiary` both silently collapsed onto `.text-muted`. They are now derived as alpha over each theme's own `--hub-sys-text-primary` (75% / 50%) — no per-theme value needed, and they survive any re-theme.
17
+ - **mixins — `focus-ring-color($variant)`** (`_helpers.scss`), the public API behind `.focus-ring-*`. It re-tints `--hub-sys-focus-ring-color` and leaves the geometry to `focus-ring()`; set it on the element, not on its focus state.
18
+ - **cascade knobs — `--hub-border-opacity`, `--hub-link-opacity`, `--hub-focus-ring-opacity`**, documented alongside the existing `--hub-bg-opacity` / `--hub-text-opacity` contract.
19
+
20
+ ### Changed
21
+
22
+ - **`.small` / `.large` are relative, not token steps.** `.small` resolves to Bootstrap's `0.875em`: it shrinks against whatever it sits in, so `.small` inside an `<h2>` stays proportional to the heading. Reach for `.fs-sm` / `.fs-lg` when you want a fixed rung of the token scale. Both classes are new in this release, so no shipped behaviour changes.
23
+ - **`border()` and `border-color()` honour `--hub-border-opacity`**, and `border-color()` gained a `$subtle` flag selecting the accent's `-border-subtle` tint. `link-color()` honours `--hub-link-opacity`. All three knobs default to `1`, so existing output is byte-identical.
24
+
8
25
  ## [22.5.6] - 2026-07-09
9
26
 
10
27
  ### Changed
@@ -264,6 +264,8 @@ Semantic neutrals. The token names are stable across themes; only the literal va
264
264
  | `--hub-sys-surface-page` | `#ffffff` | `#121212` |
265
265
  | `--hub-sys-surface-elevated` | `#f8f9fa` | `#1e1e1e` |
266
266
  | `--hub-sys-text-primary` | `#212529` | `#f8f9fa` |
267
+ | `--hub-sys-text-secondary` | `alpha 75% of text-primary` | inherits |
268
+ | `--hub-sys-text-tertiary` | `alpha 50% of text-primary` | inherits |
267
269
  | `--hub-sys-text-muted` | `#6c757d` | `#adb5bd` |
268
270
  | `--hub-sys-border-color-default` | `#dee2e6` | `#343a40` |
269
271
  | `--hub-sys-link-color` | `var(--hub-sys-color-primary)` | inherits |
@@ -512,6 +514,9 @@ Cascade knobs read by the opt-in utility sheets and their mixin equivalents. The
512
514
  | `--hub-bg-opacity` | `1` | Opacity multiplier applied by `.bg-*` / `.text-bg-*` surface utilities (set by `.bg-opacity-{10,25,50,75,100}`) | `IN_USE` | `ds/styles/utilities/surfaces.scss:47` |
513
515
  | `--hub-text-opacity` | `1` | Opacity multiplier applied by `.text-*` colour utilities (set by `.text-opacity-{25,50,75,100}`) | `IN_USE` | `ds/styles/utilities/text.scss:146` |
514
516
  | `--hub-link-underline-opacity` | `1` | Opacity multiplier for the `.link-underline-*` underline colour (set by `.link-underline-opacity-{0,10,25,50,75,100}`) | `IN_USE` | `ds/styles/utilities/text.scss:177` |
517
+ | `--hub-link-opacity` | `1` | Opacity multiplier for the `.link-*` text colour (set by `.link-opacity-{10,25,50,75,100}`) | `IN_USE` | `ds/styles/utilities/text.scss:199` |
518
+ | `--hub-border-opacity` | `1` | Opacity multiplier applied by `.border` / `.border-*` colour utilities (set by `.border-opacity-{10,25,50,75,100}`) | `IN_USE` | `ds/styles/utilities/surfaces.scss:117` |
519
+ | `--hub-focus-ring-opacity` | `0.25` | Alpha the `.focus-ring-*` utilities mix the accent with when re-tinting `--hub-sys-focus-ring-color` | `IN_USE` | `ds/styles/mixins/_helpers.scss:70` |
515
520
 
516
521
  ## `container` Variables (Inheritable base)
517
522
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ng-hub-ui-ds",
3
- "version": "22.5.6",
3
+ "version": "22.6.0",
4
4
  "license": "MIT",
5
5
  "scripts": {
6
6
  "build:tokens": "sass styles/tokens/hub-tokens.scss styles/tokens/hub-tokens.css --style=expanded --no-source-map",
@@ -60,3 +60,15 @@
60
60
  outline: 0;
61
61
  box-shadow: 0 0 0 var(--hub-sys-focus-ring-width) var(--hub-sys-focus-ring-color);
62
62
  }
63
+
64
+ /// Re-tints the ring colour token from an accent of the open map, leaving the
65
+ /// geometry to `focus-ring()`. Set it on the element, not on its focus state —
66
+ /// it declares a variable, it does not paint.
67
+ /// @param {String} $variant Accent name of the open map.
68
+ @mixin focus-ring-color($variant: primary) {
69
+ --hub-sys-focus-ring-color: color-mix(
70
+ in srgb,
71
+ var(--hub-sys-color-#{$variant}) calc(var(--hub-focus-ring-opacity, 0.25) * 100%),
72
+ transparent
73
+ );
74
+ }
@@ -18,7 +18,7 @@
18
18
  /// page surface (`body`) or `transparent`. The colour is emitted through
19
19
  /// `--hub-bg-opacity` (default 1), so `.bg-opacity-*` (or a local override of
20
20
  /// that property) fades it without extra classes.
21
- /// @param {String} $variant Accent name, or body | transparent.
21
+ /// @param {String} $variant Accent name, or body | body-secondary | body-tertiary | transparent.
22
22
  /// @param {Boolean} $subtle Use the accent's `-subtle` tint.
23
23
  @mixin bg($variant: body, $subtle: false) {
24
24
  @if $variant == transparent {
@@ -27,6 +27,12 @@
27
27
  $color: var(--hub-sys-color-#{$variant});
28
28
  @if $variant == body {
29
29
  $color: var(--hub-sys-surface-page);
30
+ } @else if $variant == body-tertiary {
31
+ $color: var(--hub-sys-surface-elevated);
32
+ } @else if $variant == body-secondary {
33
+ // One step past the elevated surface, toward the theme's ink — so it
34
+ // darkens on a light theme and lightens on a dark one.
35
+ $color: color-mix(in oklch, var(--hub-sys-surface-elevated) 92%, var(--hub-sys-color-ink));
30
36
  } @else if $subtle {
31
37
  $color: var(--hub-sys-color-#{$variant}-subtle);
32
38
  }
@@ -42,17 +48,24 @@
42
48
  color: var(--hub-sys-color-#{$variant}-on);
43
49
  }
44
50
 
45
- /// Solid border on all sides, token-driven colour.
51
+ /// Solid border on all sides, token-driven colour. The colour is emitted through
52
+ /// `--hub-border-opacity` (default 1), so `.border-opacity-*` fades it.
46
53
  /// @param {Number} $width Border width.
47
54
  /// @param {String} $color Any CSS colour; defaults to the canonical border token.
48
55
  @mixin border($width: 1px, $color: var(--hub-sys-border-color-default)) {
49
- border: $width solid $color;
56
+ border: $width solid color-mix(in srgb, #{$color} calc(var(--hub-border-opacity, 1) * 100%), transparent);
50
57
  }
51
58
 
52
- /// Border colour from an accent of the open map (keeps width/style untouched).
59
+ /// Border colour from an accent of the open map (keeps width/style untouched),
60
+ /// honouring `--hub-border-opacity`.
53
61
  /// @param {String} $variant Accent name of the open map.
54
- @mixin border-color($variant: primary) {
55
- border-color: var(--hub-sys-color-#{$variant});
62
+ /// @param {Boolean} $subtle Use the accent's `-border-subtle` tint.
63
+ @mixin border-color($variant: primary, $subtle: false) {
64
+ $color: var(--hub-sys-color-#{$variant});
65
+ @if $subtle {
66
+ $color: var(--hub-sys-color-#{$variant}-border-subtle);
67
+ }
68
+ border-color: color-mix(in srgb, #{$color} calc(var(--hub-border-opacity, 1) * 100%), transparent);
56
69
  }
57
70
 
58
71
  /// Corner radius from the canonical scale.
@@ -74,25 +74,42 @@ $_heading-scale: (
74
74
  }
75
75
 
76
76
  /// Semantic text colour — any accent of the open map (`primary`, `danger`,
77
- /// `brand`…) or the document roles `body` / `muted`. The colour is emitted
78
- /// through `--hub-text-opacity` (default 1), so `.text-opacity-*` (or a local
79
- /// override of that property) fades it without extra classes.
80
- /// @param {String} $variant Accent name, or body | muted.
77
+ /// `brand`…) or a document role.
78
+ ///
79
+ /// The document roles are the de-emphasis ramp, NOT accents: `body` (full ink),
80
+ /// `body-secondary`, `body-tertiary`, `muted`, and `body-emphasis` (the strongest).
81
+ /// They exist because `secondary` is an ACCENT — in most themes a blue — and
82
+ /// reaching for `.text-secondary` to mean "quieter body text" silently repaints
83
+ /// every caption in the brand's secondary colour.
84
+ ///
85
+ /// The colour is emitted through `--hub-text-opacity` (default 1), so
86
+ /// `.text-opacity-*` (or a local override of that property) fades it without
87
+ /// extra classes.
88
+ ///
89
+ /// @param {String} $variant Accent name, or body | body-secondary |
90
+ /// body-tertiary | body-emphasis | muted.
81
91
  @mixin text-color($variant: body) {
82
92
  $color: var(--hub-sys-color-#{$variant});
83
93
  @if $variant == body {
84
94
  $color: var(--hub-sys-text-primary);
95
+ } @else if $variant == body-emphasis {
96
+ $color: var(--hub-sys-text-emphasis, var(--hub-sys-text-primary));
97
+ } @else if $variant == body-secondary {
98
+ $color: var(--hub-sys-text-secondary, var(--hub-sys-text-muted));
99
+ } @else if $variant == body-tertiary {
100
+ $color: var(--hub-sys-text-tertiary, var(--hub-sys-text-muted));
85
101
  } @else if $variant == muted {
86
102
  $color: var(--hub-sys-text-muted);
87
103
  }
88
104
  color: color-mix(in srgb, #{$color} calc(var(--hub-text-opacity, 1) * 100%), transparent);
89
105
  }
90
106
 
91
- /// Accent-coloured link with its `-emphasis` hover/focus treatment. The
92
- /// underline colour honours `--hub-link-underline-opacity` (default 1).
107
+ /// Accent-coloured link with its `-emphasis` hover/focus treatment. The text
108
+ /// colour honours `--hub-link-opacity` and the underline
109
+ /// `--hub-link-underline-opacity` (both default 1).
93
110
  /// @param {String} $variant Accent name of the open map.
94
111
  @mixin link-color($variant: primary) {
95
- color: var(--hub-sys-color-#{$variant});
112
+ color: color-mix(in srgb, var(--hub-sys-color-#{$variant}) calc(var(--hub-link-opacity, 1) * 100%), transparent);
96
113
  text-decoration-color: color-mix(
97
114
  in srgb,
98
115
  var(--hub-sys-color-#{$variant}) calc(var(--hub-link-underline-opacity, 1) * 100%),
@@ -101,7 +118,11 @@ $_heading-scale: (
101
118
 
102
119
  &:hover,
103
120
  &:focus {
104
- color: var(--hub-sys-color-#{$variant}-emphasis);
121
+ color: color-mix(
122
+ in srgb,
123
+ var(--hub-sys-color-#{$variant}-emphasis) calc(var(--hub-link-opacity, 1) * 100%),
124
+ transparent
125
+ );
105
126
  text-decoration-color: color-mix(
106
127
  in srgb,
107
128
  var(--hub-sys-color-#{$variant}-emphasis) calc(var(--hub-link-underline-opacity, 1) * 100%),
@@ -454,6 +454,11 @@
454
454
  Text
455
455
  ---------------------------------------------------------- */
456
456
  --hub-sys-text-primary: var(--hub-ref-color-gray-900, #212529);
457
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
458
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
459
+ not the `secondary` ACCENT (a blue in most themes). */
460
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
461
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
457
462
  --hub-sys-text-muted: var(--hub-ref-color-gray-600, #6c757d);
458
463
  --hub-sys-color-text-subtle: var(--hub-sys-text-muted, #6c757d);
459
464
  --hub-sys-link-color: var(--hub-sys-color-primary, #0d6efd);
@@ -600,6 +605,11 @@
600
605
  --hub-sys-border-color-default: var(--bs-border-color, #dee2e6);
601
606
  --hub-sys-surface-page: var(--bs-body-bg, #ffffff);
602
607
  --hub-sys-text-primary: var(--bs-body-color, #212529);
608
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
609
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
610
+ not the `secondary` ACCENT (a blue in most themes). */
611
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
612
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
603
613
  }
604
614
 
605
615
  /* ============================================================
@@ -625,6 +635,11 @@
625
635
  --hub-sys-surface-page: var(--hub-ref-surface-1, #ffffff);
626
636
  --hub-sys-surface-elevated: var(--hub-ref-surface-2, #f8f9fa);
627
637
  --hub-sys-text-primary: var(--hub-ref-color-gray-900, #212529);
638
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
639
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
640
+ not the `secondary` ACCENT (a blue in most themes). */
641
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
642
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
628
643
  --hub-sys-text-muted: var(--hub-ref-color-gray-600, #6c757d);
629
644
  --hub-sys-border-color-default: var(--hub-ref-color-gray-300, #dee2e6);
630
645
  --hub-sys-state-hover-bg: rgba(0, 0, 0, 0.075);
@@ -647,6 +662,11 @@
647
662
  --hub-sys-surface-page: var(--bs-body-bg, #ffffff);
648
663
  --hub-sys-surface-elevated: var(--bs-light, #f8f9fa);
649
664
  --hub-sys-text-primary: var(--bs-body-color, #212529);
665
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
666
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
667
+ not the `secondary` ACCENT (a blue in most themes). */
668
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
669
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
650
670
  --hub-sys-text-muted: var(--bs-secondary-color, #6c757d);
651
671
  --hub-sys-link-color: var(--bs-link-color, #0d6efd);
652
672
  --hub-sys-link-hover-color: var(--bs-link-hover-color, #0a58ca);
@@ -694,6 +714,11 @@
694
714
  Text
695
715
  ---------------------------------------------------------- */
696
716
  --hub-sys-text-primary: var(--hub-ref-color-gray-100, #f8f9fa);
717
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
718
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
719
+ not the `secondary` ACCENT (a blue in most themes). */
720
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
721
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
697
722
  --hub-sys-text-muted: var(--hub-ref-color-gray-500, #adb5bd);
698
723
  --hub-sys-link-color: var(--hub-ref-color-blue-300, #6ea8fe);
699
724
  --hub-sys-link-hover-color: var(--hub-ref-color-blue-200, #9ec5fe);
@@ -735,6 +760,11 @@
735
760
  --hub-sys-surface-page: #fff7ed;
736
761
  --hub-sys-surface-elevated: #ffedd5;
737
762
  --hub-sys-text-primary: #7c2d12;
763
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
764
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
765
+ not the `secondary` ACCENT (a blue in most themes). */
766
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
767
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
738
768
  --hub-sys-text-muted: #9a3412;
739
769
  --hub-sys-link-color: #c2410c;
740
770
  --hub-sys-link-hover-color: #9a3412;
@@ -767,6 +797,11 @@
767
797
  --hub-sys-surface-page: #f0fdf4;
768
798
  --hub-sys-surface-elevated: #dcfce7;
769
799
  --hub-sys-text-primary: #14532d;
800
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
801
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
802
+ not the `secondary` ACCENT (a blue in most themes). */
803
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
804
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
770
805
  --hub-sys-text-muted: #3f6212;
771
806
  --hub-sys-link-color: #166534;
772
807
  --hub-sys-link-hover-color: #14532d;
@@ -799,6 +834,11 @@
799
834
  --hub-sys-surface-page: #f9fafb;
800
835
  --hub-sys-surface-elevated: #f3f4f6;
801
836
  --hub-sys-text-primary: #111827;
837
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
838
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
839
+ not the `secondary` ACCENT (a blue in most themes). */
840
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
841
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
802
842
  --hub-sys-text-muted: #4b5563;
803
843
  --hub-sys-link-color: #1f2937;
804
844
  --hub-sys-link-hover-color: #111827;
@@ -860,6 +900,11 @@
860
900
  Text — green phosphor, cyan links
861
901
  ---------------------------------------------------------- */
862
902
  --hub-sys-text-primary: #66f08f;
903
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
904
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
905
+ not the `secondary` ACCENT (a blue in most themes). */
906
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
907
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
863
908
  --hub-sys-text-muted: #3f9e63;
864
909
  --hub-sys-link-color: #56e1e6;
865
910
  --hub-sys-link-hover-color: #8dffb0;
@@ -463,6 +463,11 @@ $hub-accents-terminal: (
463
463
  Text
464
464
  ---------------------------------------------------------- */
465
465
  --hub-sys-text-primary: var(--hub-ref-color-gray-900, #212529);
466
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
467
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
468
+ not the `secondary` ACCENT (a blue in most themes). */
469
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
470
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
466
471
  --hub-sys-text-muted: var(--hub-ref-color-gray-600, #6c757d);
467
472
  --hub-sys-color-text-subtle: var(--hub-sys-text-muted, #6c757d);
468
473
  --hub-sys-link-color: var(--hub-sys-color-primary, #0d6efd);
@@ -616,6 +621,11 @@ $hub-accents-terminal: (
616
621
  --hub-sys-border-color-default: var(--bs-border-color, #dee2e6);
617
622
  --hub-sys-surface-page: var(--bs-body-bg, #ffffff);
618
623
  --hub-sys-text-primary: var(--bs-body-color, #212529);
624
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
625
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
626
+ not the `secondary` ACCENT (a blue in most themes). */
627
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
628
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
619
629
  }
620
630
 
621
631
  /* ============================================================
@@ -634,6 +644,11 @@ $hub-accents-terminal: (
634
644
  --hub-sys-surface-page: var(--hub-ref-surface-1, #ffffff);
635
645
  --hub-sys-surface-elevated: var(--hub-ref-surface-2, #f8f9fa);
636
646
  --hub-sys-text-primary: var(--hub-ref-color-gray-900, #212529);
647
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
648
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
649
+ not the `secondary` ACCENT (a blue in most themes). */
650
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
651
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
637
652
  --hub-sys-text-muted: var(--hub-ref-color-gray-600, #6c757d);
638
653
  --hub-sys-border-color-default: var(--hub-ref-color-gray-300, #dee2e6);
639
654
  --hub-sys-state-hover-bg: rgba(0, 0, 0, 0.075);
@@ -653,6 +668,11 @@ $hub-accents-terminal: (
653
668
  --hub-sys-surface-page: var(--bs-body-bg, #ffffff);
654
669
  --hub-sys-surface-elevated: var(--bs-light, #f8f9fa);
655
670
  --hub-sys-text-primary: var(--bs-body-color, #212529);
671
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
672
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
673
+ not the `secondary` ACCENT (a blue in most themes). */
674
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
675
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
656
676
  --hub-sys-text-muted: var(--bs-secondary-color, #6c757d);
657
677
  --hub-sys-link-color: var(--bs-link-color, #0d6efd);
658
678
  --hub-sys-link-hover-color: var(--bs-link-hover-color, #0a58ca);
@@ -701,6 +721,11 @@ $hub-accents-terminal: (
701
721
  Text
702
722
  ---------------------------------------------------------- */
703
723
  --hub-sys-text-primary: var(--hub-ref-color-gray-100, #f8f9fa);
724
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
725
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
726
+ not the `secondary` ACCENT (a blue in most themes). */
727
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
728
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
704
729
  --hub-sys-text-muted: var(--hub-ref-color-gray-500, #adb5bd);
705
730
  --hub-sys-link-color: var(--hub-ref-color-blue-300, #6ea8fe);
706
731
  --hub-sys-link-hover-color: var(--hub-ref-color-blue-200, #9ec5fe);
@@ -743,6 +768,11 @@ $hub-accents-terminal: (
743
768
  --hub-sys-surface-page: #fff7ed;
744
769
  --hub-sys-surface-elevated: #ffedd5;
745
770
  --hub-sys-text-primary: #7c2d12;
771
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
772
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
773
+ not the `secondary` ACCENT (a blue in most themes). */
774
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
775
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
746
776
  --hub-sys-text-muted: #9a3412;
747
777
  --hub-sys-link-color: #c2410c;
748
778
  --hub-sys-link-hover-color: #9a3412;
@@ -773,6 +803,11 @@ $hub-accents-terminal: (
773
803
  --hub-sys-surface-page: #f0fdf4;
774
804
  --hub-sys-surface-elevated: #dcfce7;
775
805
  --hub-sys-text-primary: #14532d;
806
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
807
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
808
+ not the `secondary` ACCENT (a blue in most themes). */
809
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
810
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
776
811
  --hub-sys-text-muted: #3f6212;
777
812
  --hub-sys-link-color: #166534;
778
813
  --hub-sys-link-hover-color: #14532d;
@@ -803,6 +838,11 @@ $hub-accents-terminal: (
803
838
  --hub-sys-surface-page: #f9fafb;
804
839
  --hub-sys-surface-elevated: #f3f4f6;
805
840
  --hub-sys-text-primary: #111827;
841
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
842
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
843
+ not the `secondary` ACCENT (a blue in most themes). */
844
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
845
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
806
846
  --hub-sys-text-muted: #4b5563;
807
847
  --hub-sys-link-color: #1f2937;
808
848
  --hub-sys-link-hover-color: #111827;
@@ -866,6 +906,11 @@ $hub-accents-terminal: (
866
906
  Text — green phosphor, cyan links
867
907
  ---------------------------------------------------------- */
868
908
  --hub-sys-text-primary: #66f08f;
909
+ /* The de-emphasis ramp: alpha over the theme's own ink, so it follows any
910
+ re-theme without a per-theme value. `secondary` here is the TEXT role,
911
+ not the `secondary` ACCENT (a blue in most themes). */
912
+ --hub-sys-text-secondary: color-mix(in srgb, var(--hub-sys-text-primary) 75%, transparent);
913
+ --hub-sys-text-tertiary: color-mix(in srgb, var(--hub-sys-text-primary) 50%, transparent);
869
914
  --hub-sys-text-muted: #3f9e63;
870
915
  --hub-sys-link-color: #56e1e6;
871
916
  --hub-sys-link-hover-color: #8dffb0;
@@ -152,6 +152,10 @@
152
152
  display: grid;
153
153
  }
154
154
 
155
+ .d-inline-grid {
156
+ display: inline-grid;
157
+ }
158
+
155
159
  .d-block {
156
160
  display: block;
157
161
  }
@@ -771,6 +775,18 @@
771
775
  min-width: 100vw;
772
776
  }
773
777
 
778
+ /* A flex/grid item's `min-width` and `min-height` default to `auto`, which is the
779
+ content's intrinsic size — so `text-overflow: ellipsis` never fires and a scroll
780
+ container never shrinks. These two reset that, and there is no Bootstrap name for
781
+ them: `.min-w-0` / `.min-h-0` follow the `min-vw-100` convention already here. */
782
+ .min-w-0 {
783
+ min-width: 0;
784
+ }
785
+
786
+ .min-h-0 {
787
+ min-height: 0;
788
+ }
789
+
774
790
  .h-auto {
775
791
  height: auto;
776
792
  }
@@ -1141,6 +1157,80 @@
1141
1157
  box-shadow: 0 0 0 var(--hub-sys-focus-ring-width) var(--hub-sys-focus-ring-color);
1142
1158
  }
1143
1159
 
1160
+ /* `.focus-ring-*` only re-tints the ring token — pair it with `.focus-ring`
1161
+ (or any component that already draws one) to see the colour change. */
1162
+ .focus-ring-primary {
1163
+ --hub-sys-focus-ring-color: color-mix(
1164
+ in srgb,
1165
+ var(--hub-sys-color-primary) calc(var(--hub-focus-ring-opacity, 0.25) * 100%),
1166
+ transparent
1167
+ );
1168
+ }
1169
+
1170
+ .focus-ring-secondary {
1171
+ --hub-sys-focus-ring-color: color-mix(
1172
+ in srgb,
1173
+ var(--hub-sys-color-secondary) calc(var(--hub-focus-ring-opacity, 0.25) * 100%),
1174
+ transparent
1175
+ );
1176
+ }
1177
+
1178
+ .focus-ring-success {
1179
+ --hub-sys-focus-ring-color: color-mix(
1180
+ in srgb,
1181
+ var(--hub-sys-color-success) calc(var(--hub-focus-ring-opacity, 0.25) * 100%),
1182
+ transparent
1183
+ );
1184
+ }
1185
+
1186
+ .focus-ring-danger {
1187
+ --hub-sys-focus-ring-color: color-mix(
1188
+ in srgb,
1189
+ var(--hub-sys-color-danger) calc(var(--hub-focus-ring-opacity, 0.25) * 100%),
1190
+ transparent
1191
+ );
1192
+ }
1193
+
1194
+ .focus-ring-warning {
1195
+ --hub-sys-focus-ring-color: color-mix(
1196
+ in srgb,
1197
+ var(--hub-sys-color-warning) calc(var(--hub-focus-ring-opacity, 0.25) * 100%),
1198
+ transparent
1199
+ );
1200
+ }
1201
+
1202
+ .focus-ring-info {
1203
+ --hub-sys-focus-ring-color: color-mix(
1204
+ in srgb,
1205
+ var(--hub-sys-color-info) calc(var(--hub-focus-ring-opacity, 0.25) * 100%),
1206
+ transparent
1207
+ );
1208
+ }
1209
+
1210
+ .focus-ring-neutral {
1211
+ --hub-sys-focus-ring-color: color-mix(
1212
+ in srgb,
1213
+ var(--hub-sys-color-neutral) calc(var(--hub-focus-ring-opacity, 0.25) * 100%),
1214
+ transparent
1215
+ );
1216
+ }
1217
+
1218
+ .focus-ring-light {
1219
+ --hub-sys-focus-ring-color: color-mix(
1220
+ in srgb,
1221
+ var(--hub-sys-color-light) calc(var(--hub-focus-ring-opacity, 0.25) * 100%),
1222
+ transparent
1223
+ );
1224
+ }
1225
+
1226
+ .focus-ring-dark {
1227
+ --hub-sys-focus-ring-color: color-mix(
1228
+ in srgb,
1229
+ var(--hub-sys-color-dark) calc(var(--hub-focus-ring-opacity, 0.25) * 100%),
1230
+ transparent
1231
+ );
1232
+ }
1233
+
1144
1234
  .visually-hidden,
1145
1235
  .visually-hidden-focusable:not(:focus):not(:focus-within) {
1146
1236
  position: absolute !important;
@@ -1203,6 +1293,9 @@
1203
1293
  .d-print-grid {
1204
1294
  display: grid;
1205
1295
  }
1296
+ .d-print-inline-grid {
1297
+ display: inline-grid;
1298
+ }
1206
1299
  .d-print-table {
1207
1300
  display: table;
1208
1301
  }
@@ -1235,6 +1328,9 @@
1235
1328
  .d-sm-grid {
1236
1329
  display: grid;
1237
1330
  }
1331
+ .d-sm-inline-grid {
1332
+ display: inline-grid;
1333
+ }
1238
1334
  .d-sm-block {
1239
1335
  display: block;
1240
1336
  }
@@ -1598,6 +1694,9 @@
1598
1694
  .d-md-grid {
1599
1695
  display: grid;
1600
1696
  }
1697
+ .d-md-inline-grid {
1698
+ display: inline-grid;
1699
+ }
1601
1700
  .d-md-block {
1602
1701
  display: block;
1603
1702
  }
@@ -1961,6 +2060,9 @@
1961
2060
  .d-lg-grid {
1962
2061
  display: grid;
1963
2062
  }
2063
+ .d-lg-inline-grid {
2064
+ display: inline-grid;
2065
+ }
1964
2066
  .d-lg-block {
1965
2067
  display: block;
1966
2068
  }
@@ -2324,6 +2426,9 @@
2324
2426
  .d-xl-grid {
2325
2427
  display: grid;
2326
2428
  }
2429
+ .d-xl-inline-grid {
2430
+ display: inline-grid;
2431
+ }
2327
2432
  .d-xl-block {
2328
2433
  display: block;
2329
2434
  }
@@ -2687,6 +2792,9 @@
2687
2792
  .d-xxl-grid {
2688
2793
  display: grid;
2689
2794
  }
2795
+ .d-xxl-inline-grid {
2796
+ display: inline-grid;
2797
+ }
2690
2798
  .d-xxl-block {
2691
2799
  display: block;
2692
2800
  }
@@ -56,6 +56,9 @@ $_steps: 0 1 2 3 4 5;
56
56
  .d-grid {
57
57
  display: grid;
58
58
  }
59
+ .d-inline-grid {
60
+ display: inline-grid;
61
+ }
59
62
  .d-block {
60
63
  display: block;
61
64
  }
@@ -277,6 +280,17 @@ $_steps: 0 1 2 3 4 5;
277
280
  .min-vw-100 {
278
281
  min-width: 100vw;
279
282
  }
283
+
284
+ /* A flex/grid item's `min-width` and `min-height` default to `auto`, which is the
285
+ content's intrinsic size — so `text-overflow: ellipsis` never fires and a scroll
286
+ container never shrinks. These two reset that, and there is no Bootstrap name for
287
+ them: `.min-w-0` / `.min-h-0` follow the `min-vw-100` convention already here. */
288
+ .min-w-0 {
289
+ min-width: 0;
290
+ }
291
+ .min-h-0 {
292
+ min-height: 0;
293
+ }
280
294
  .h-auto {
281
295
  height: auto;
282
296
  }
@@ -558,6 +572,13 @@ $_steps: 0 1 2 3 4 5;
558
572
  .focus-ring:focus {
559
573
  @include helpers.focus-ring();
560
574
  }
575
+ /* `.focus-ring-*` only re-tints the ring token — pair it with `.focus-ring`
576
+ (or any component that already draws one) to see the colour change. */
577
+ @each $variant in (primary, secondary, success, danger, warning, info, neutral, light, dark) {
578
+ .focus-ring-#{$variant} {
579
+ @include helpers.focus-ring-color($variant);
580
+ }
581
+ }
561
582
  .visually-hidden,
562
583
  .visually-hidden-focusable:not(:focus):not(:focus-within) {
563
584
  @include helpers.visually-hidden();
@@ -604,6 +625,9 @@ $_steps: 0 1 2 3 4 5;
604
625
  .d-print-grid {
605
626
  display: grid;
606
627
  }
628
+ .d-print-inline-grid {
629
+ display: inline-grid;
630
+ }
607
631
  .d-print-table {
608
632
  display: table;
609
633
  }
@@ -629,7 +653,7 @@ $_steps: 0 1 2 3 4 5;
629
653
  @each $bp-name, $bp-width in bp.$hub-breakpoints {
630
654
  @include bp.media-breakpoint-up($bp-name) {
631
655
  /* display */
632
- @each $d in (flex, inline-flex, grid, block, inline-block, inline, table, table-row, table-cell, none) {
656
+ @each $d in (flex, inline-flex, grid, inline-grid, block, inline-block, inline, table, table-row, table-cell, none) {
633
657
  .d-#{$bp-name}-#{$d} {
634
658
  display: $d;
635
659
  }