ng-hub-ui-nav 22.5.0 → 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.
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ng-hub-ui-nav",
|
|
3
|
-
"version": "22.
|
|
3
|
+
"version": "22.6.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "A flexible, accessible, and customizable navigation component for Angular 21, part of the ng-hub-ui family.",
|
|
6
6
|
"author": "Carlos Morcillo <carlos.morcillo@me.com> (https://www.carlosmorcillo.com)",
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// hub-nav-theme — one-call token theming for `<hub-nav>`
|
|
3
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
4
|
+
//
|
|
5
|
+
// Override the most useful `--hub-nav-*` design tokens in a single include. Every
|
|
6
|
+
// parameter is OPTIONAL and defaults to `null`: only the parameters you pass are
|
|
7
|
+
// emitted, so the rest keep their defaults. For any token not exposed here, set the
|
|
8
|
+
// `--hub-nav-*` custom property directly — this mixin is sugar for the common knobs,
|
|
9
|
+
// not a replacement for the full token surface.
|
|
10
|
+
//
|
|
11
|
+
// `$accent` feeds the single `--hub-nav-accent` slot; the component derives the
|
|
12
|
+
// `-emphasis` / `-subtle` / `-on` family from it at runtime, so one colour re-tones
|
|
13
|
+
// the active indicator and hover accents. Pass any value `resolveHubAccent` accepts
|
|
14
|
+
// (a semantic name, a registered accent, or a literal `#hex` / `rgb()` / `oklch()`).
|
|
15
|
+
//
|
|
16
|
+
// @example
|
|
17
|
+
//
|
|
18
|
+
// @use 'ng-hub-ui-nav/styles' as *;
|
|
19
|
+
//
|
|
20
|
+
// .app-shell nav {
|
|
21
|
+
// @include hub-nav-theme($accent: var(--hub-sys-color-brand), $item-border-radius: 0.5rem);
|
|
22
|
+
// }
|
|
23
|
+
//
|
|
24
|
+
// scss-docs-start hub-nav-theme
|
|
25
|
+
@mixin hub-nav-theme(
|
|
26
|
+
$accent: null, // --hub-nav-accent (active indicator + hover accents)
|
|
27
|
+
$bg: null, // --hub-nav-bg (bar surface)
|
|
28
|
+
$color: null, // --hub-nav-color (bar text)
|
|
29
|
+
$border-color: null, // --hub-nav-border-color
|
|
30
|
+
$gap: null, // --hub-nav-gap (spacing between items)
|
|
31
|
+
$padding-x: null, // --hub-nav-padding-x
|
|
32
|
+
$padding-y: null, // --hub-nav-padding-y
|
|
33
|
+
$item-color: null, // --hub-nav-item-color
|
|
34
|
+
$item-active-bg: null, // --hub-nav-item-active-bg
|
|
35
|
+
$item-active-color: null, // --hub-nav-item-active-color
|
|
36
|
+
$item-border-radius: null, // --hub-nav-item-border-radius
|
|
37
|
+
$item-font-size: null, // --hub-nav-item-font-size
|
|
38
|
+
$item-padding-x: null, // --hub-nav-item-padding-x
|
|
39
|
+
$item-padding-y: null // --hub-nav-item-padding-y
|
|
40
|
+
) {
|
|
41
|
+
@if $accent != null {
|
|
42
|
+
--hub-nav-accent: #{$accent};
|
|
43
|
+
}
|
|
44
|
+
@if $bg != null {
|
|
45
|
+
--hub-nav-bg: #{$bg};
|
|
46
|
+
}
|
|
47
|
+
@if $color != null {
|
|
48
|
+
--hub-nav-color: #{$color};
|
|
49
|
+
}
|
|
50
|
+
@if $border-color != null {
|
|
51
|
+
--hub-nav-border-color: #{$border-color};
|
|
52
|
+
}
|
|
53
|
+
@if $gap != null {
|
|
54
|
+
--hub-nav-gap: #{$gap};
|
|
55
|
+
}
|
|
56
|
+
@if $padding-x != null {
|
|
57
|
+
--hub-nav-padding-x: #{$padding-x};
|
|
58
|
+
}
|
|
59
|
+
@if $padding-y != null {
|
|
60
|
+
--hub-nav-padding-y: #{$padding-y};
|
|
61
|
+
}
|
|
62
|
+
@if $item-color != null {
|
|
63
|
+
--hub-nav-item-color: #{$item-color};
|
|
64
|
+
}
|
|
65
|
+
@if $item-active-bg != null {
|
|
66
|
+
--hub-nav-item-active-bg: #{$item-active-bg};
|
|
67
|
+
}
|
|
68
|
+
@if $item-active-color != null {
|
|
69
|
+
--hub-nav-item-active-color: #{$item-active-color};
|
|
70
|
+
}
|
|
71
|
+
@if $item-border-radius != null {
|
|
72
|
+
--hub-nav-item-border-radius: #{$item-border-radius};
|
|
73
|
+
}
|
|
74
|
+
@if $item-font-size != null {
|
|
75
|
+
--hub-nav-item-font-size: #{$item-font-size};
|
|
76
|
+
}
|
|
77
|
+
@if $item-padding-x != null {
|
|
78
|
+
--hub-nav-item-padding-x: #{$item-padding-x};
|
|
79
|
+
}
|
|
80
|
+
@if $item-padding-y != null {
|
|
81
|
+
--hub-nav-item-padding-y: #{$item-padding-y};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// scss-docs-end hub-nav-theme
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
// ──────────────────────────────────────────────────────
|
|
2
|
+
// hub-nav — Design Tokens
|
|
3
|
+
// References hub-sys / hub-ref tokens from the design system.
|
|
4
|
+
// ──────────────────────────────────────────────────────
|
|
5
|
+
|
|
6
|
+
:root,
|
|
7
|
+
:host {
|
|
8
|
+
// ── Layout ──
|
|
9
|
+
--hub-nav-height: 3.5rem;
|
|
10
|
+
--hub-nav-padding-x: var(--hub-ref-space-3, 1rem);
|
|
11
|
+
--hub-nav-padding-y: var(--hub-ref-space-2, 0.5rem);
|
|
12
|
+
--hub-nav-gap: var(--hub-ref-space-1, 0.25rem);
|
|
13
|
+
--hub-nav-horizontal-padding-y: 0;
|
|
14
|
+
--hub-nav-horizontal-padding-x: 0;
|
|
15
|
+
--hub-nav-horizontal-row-gap: 0;
|
|
16
|
+
--hub-nav-horizontal-items-justify: center;
|
|
17
|
+
--hub-nav-horizontal-items-overflow-x: auto;
|
|
18
|
+
--hub-nav-horizontal-items-overflow-y: hidden;
|
|
19
|
+
--hub-nav-vertical-items-overflow-y: auto;
|
|
20
|
+
--hub-nav-vertical-items-overflow-x: hidden;
|
|
21
|
+
--hub-nav-vertical-panel-padding-inline: var(--hub-ref-space-2, 0.5rem);
|
|
22
|
+
--hub-nav-vertical-panel-padding-block: 0;
|
|
23
|
+
--hub-nav-horizontal-panel-padding-y: var(--hub-ref-space-2, 0.5rem);
|
|
24
|
+
--hub-nav-horizontal-panel-padding-x: 0;
|
|
25
|
+
--hub-nav-scrollbar-width: none;
|
|
26
|
+
--hub-nav-scrollbar-color: transparent transparent;
|
|
27
|
+
--hub-nav-scrollbar-webkit-size: 0;
|
|
28
|
+
--hub-nav-scrollbar-thumb-color: transparent;
|
|
29
|
+
--hub-nav-scrollbar-track-color: transparent;
|
|
30
|
+
--hub-nav-scrollbar-thumb-radius: var(--hub-ref-radius-pill, 50rem);
|
|
31
|
+
|
|
32
|
+
// ── Colours ──
|
|
33
|
+
// Single semantic accent driving the hover/active affordances. Defaults to
|
|
34
|
+
// `primary` and is re-based per `variant` (see the loop below) or inline by
|
|
35
|
+
// the component, so the whole nav recolours from one hook.
|
|
36
|
+
--hub-nav-accent: var(--hub-sys-color-primary, #0d6efd);
|
|
37
|
+
// Subtle tint of the accent for the soft hover/active surfaces (derived with
|
|
38
|
+
// the canonical design-system formula, so it follows the accent — and the
|
|
39
|
+
// variant — automatically, matching the ds `-subtle` tints exactly).
|
|
40
|
+
--hub-nav-accent-subtle: color-mix(in oklch, var(--hub-nav-accent) 12%, var(--hub-sys-surface-page, #ffffff));
|
|
41
|
+
// Strong/emphasis shade of the accent, mixed over the theme ink. Mirrors the
|
|
42
|
+
// design-system `-emphasis` role so the accent text reads with enough contrast.
|
|
43
|
+
--hub-nav-accent-emphasis: color-mix(in oklch, var(--hub-nav-accent) 80%, var(--hub-sys-color-ink, #212529));
|
|
44
|
+
// Contrast / on-color: text that sits ON the accent. Grayscale flip driven by
|
|
45
|
+
// the accent's own lightness (dark accents → white text, light accents → near
|
|
46
|
+
// black), recomputed at runtime with the accent — no second token needed.
|
|
47
|
+
--hub-nav-accent-on: oklch(from var(--hub-nav-accent) clamp(0, (0.62 - l) * 1000, 1) 0 h);
|
|
48
|
+
// The nav surface carries a faint wash of the accent, so each `variant`
|
|
49
|
+
// reads as a distinctly-themed surface (not just the active item).
|
|
50
|
+
--hub-nav-bg: color-mix(in oklch, var(--hub-nav-accent) 5%, var(--hub-sys-surface-page, #fff));
|
|
51
|
+
--hub-nav-color: var(--hub-sys-text-primary, #212529);
|
|
52
|
+
--hub-nav-border-color: var(--hub-sys-border-color-default, #dee2e6);
|
|
53
|
+
--hub-nav-border-width: 1px;
|
|
54
|
+
--hub-nav-border-style: solid;
|
|
55
|
+
|
|
56
|
+
// ── Brand ──
|
|
57
|
+
--hub-nav-brand-font-size: var(--hub-ref-font-size-lg, 1.25rem);
|
|
58
|
+
--hub-nav-brand-font-weight: var(--hub-ref-font-weight-semibold, 600);
|
|
59
|
+
--hub-nav-brand-color: var(--hub-sys-text-primary, #212529);
|
|
60
|
+
--hub-nav-brand-padding-x: var(--hub-ref-space-2, 0.5rem);
|
|
61
|
+
|
|
62
|
+
// ── Items ──
|
|
63
|
+
--hub-nav-item-padding-x: var(--hub-ref-space-3, 1rem);
|
|
64
|
+
--hub-nav-item-padding-y: var(--hub-ref-space-2, 0.5rem);
|
|
65
|
+
--hub-nav-item-color: var(--hub-sys-text-primary, #212529);
|
|
66
|
+
--hub-nav-item-font-size: var(--hub-ref-font-size-base, 1rem);
|
|
67
|
+
--hub-nav-item-font-weight: var(--hub-ref-font-weight-base, 400);
|
|
68
|
+
--hub-nav-item-border-radius: var(--hub-ref-radius-sm, 0.25rem);
|
|
69
|
+
--hub-nav-item-transition: var(--hub-sys-transition-fast, all 0.15s ease-in-out);
|
|
70
|
+
|
|
71
|
+
// ── Item Hover ── (soft accent tint)
|
|
72
|
+
--hub-nav-item-hover-bg: color-mix(in oklch, var(--hub-nav-accent) 8%, var(--hub-sys-surface-page, #fff));
|
|
73
|
+
--hub-nav-item-hover-color: var(--hub-nav-accent);
|
|
74
|
+
|
|
75
|
+
// ── Item Active ── (soft tint + accent text + accent indicator bar)
|
|
76
|
+
--hub-nav-item-active-bg: var(--hub-nav-accent-subtle);
|
|
77
|
+
--hub-nav-item-active-color: var(--hub-nav-accent);
|
|
78
|
+
--hub-nav-item-active-font-weight: var(--hub-ref-font-weight-semibold, 600);
|
|
79
|
+
--hub-nav-item-active-indicator-color: var(--hub-nav-accent);
|
|
80
|
+
--hub-nav-item-active-indicator-size: 3px;
|
|
81
|
+
|
|
82
|
+
// ── Item Disabled ──
|
|
83
|
+
--hub-nav-item-disabled-color: var(--hub-sys-text-muted, #6c757d);
|
|
84
|
+
--hub-nav-item-disabled-opacity: var(--hub-sys-opacity-disabled, 0.65);
|
|
85
|
+
|
|
86
|
+
// ── Dropdown ──
|
|
87
|
+
--hub-nav-dropdown-bg: var(--hub-sys-surface-elevated, #f8f9fa);
|
|
88
|
+
--hub-nav-dropdown-color: var(--hub-sys-text-primary, #212529);
|
|
89
|
+
--hub-nav-dropdown-border-color: var(--hub-sys-border-color-default, #dee2e6);
|
|
90
|
+
--hub-nav-dropdown-border-radius: var(--hub-nav-item-border-radius, var(--hub-ref-radius-sm, 0.25rem));
|
|
91
|
+
--hub-nav-dropdown-shadow: var(--hub-sys-shadow, 0 0.5rem 1rem rgba(0, 0, 0, 0.15));
|
|
92
|
+
--hub-nav-dropdown-padding-y: var(--hub-ref-space-2, 0.5rem);
|
|
93
|
+
--hub-nav-dropdown-min-width: 12rem;
|
|
94
|
+
--hub-nav-dropdown-zindex: var(--hub-sys-zindex-dropdown, 1000);
|
|
95
|
+
|
|
96
|
+
// ── Caret ──
|
|
97
|
+
--hub-nav-caret-size: 0.3rem;
|
|
98
|
+
--hub-nav-caret-color: currentColor;
|
|
99
|
+
|
|
100
|
+
// ── Header (item type) ──
|
|
101
|
+
--hub-nav-header-font-size: var(--hub-ref-font-size-sm, 0.875rem);
|
|
102
|
+
--hub-nav-header-font-weight: var(--hub-ref-font-weight-semibold, 600);
|
|
103
|
+
--hub-nav-header-color: var(--hub-sys-text-muted, #6c757d);
|
|
104
|
+
--hub-nav-header-padding-x: var(--hub-ref-space-3, 1rem);
|
|
105
|
+
--hub-nav-header-padding-y: var(--hub-ref-space-1, 0.25rem);
|
|
106
|
+
--hub-nav-header-margin-top: var(--hub-ref-space-3, 1rem);
|
|
107
|
+
--hub-nav-header-margin-inline-start: var(--hub-ref-space-3, 1rem);
|
|
108
|
+
--hub-nav-header-horizontal-padding-inline-start: 2rem;
|
|
109
|
+
|
|
110
|
+
// ── Separator ──
|
|
111
|
+
--hub-nav-separator-color: var(--hub-sys-border-color-default, #dee2e6);
|
|
112
|
+
--hub-nav-separator-margin-y: var(--hub-ref-space-2, 0.5rem);
|
|
113
|
+
|
|
114
|
+
// ── Badge ──
|
|
115
|
+
--hub-nav-badge-font-size: var(--hub-ref-font-size-xs, 0.75rem);
|
|
116
|
+
--hub-nav-badge-padding-x: 0.5em;
|
|
117
|
+
--hub-nav-badge-padding-y: 0.25em;
|
|
118
|
+
--hub-nav-badge-bg: var(--hub-sys-color-danger, #dc3545);
|
|
119
|
+
--hub-nav-badge-color: var(--hub-ref-color-white, #fff);
|
|
120
|
+
--hub-nav-badge-border-radius: var(--hub-ref-radius-pill, 50rem);
|
|
121
|
+
|
|
122
|
+
// ── Toggler (hamburger) ──
|
|
123
|
+
--hub-nav-toggler-padding-x: var(--hub-ref-space-2, 0.5rem);
|
|
124
|
+
--hub-nav-toggler-padding-y: var(--hub-ref-space-1, 0.25rem);
|
|
125
|
+
--hub-nav-toggler-font-size: var(--hub-ref-font-size-lg, 1.25rem);
|
|
126
|
+
--hub-nav-toggler-color: var(--hub-sys-text-primary, #212529);
|
|
127
|
+
--hub-nav-toggler-border-color: var(--hub-sys-border-color-default, #dee2e6);
|
|
128
|
+
--hub-nav-toggler-border-radius: var(--hub-ref-radius-sm, 0.25rem);
|
|
129
|
+
|
|
130
|
+
// ── Mobile Panel ──
|
|
131
|
+
--hub-nav-mobile-bg: var(--hub-sys-surface-page, #fff);
|
|
132
|
+
--hub-nav-mobile-color: var(--hub-sys-text-primary, #212529);
|
|
133
|
+
--hub-nav-mobile-width: 18rem;
|
|
134
|
+
--hub-nav-mobile-zindex: var(--hub-sys-zindex-fixed, 1030);
|
|
135
|
+
--hub-nav-mobile-backdrop-bg: rgba(0, 0, 0, 0.5);
|
|
136
|
+
--hub-nav-mobile-transition: var(--hub-sys-transition-base, all 0.2s ease-in-out);
|
|
137
|
+
|
|
138
|
+
// ── Accordion mode (vertical expand) ──
|
|
139
|
+
--hub-nav-accordion-indent: var(--hub-ref-space-3, 1rem);
|
|
140
|
+
// Duration + easing of the expand ANIMATION. It intentionally does NOT
|
|
141
|
+
// reference `--hub-sys-transition-collapse`: the ds value is a transition
|
|
142
|
+
// shorthand carrying a property name (`height 0.35s ease`), which is invalid
|
|
143
|
+
// inside `animation` and would silently disable it. Timing matches ds.
|
|
144
|
+
--hub-nav-accordion-transition: 0.35s ease;
|
|
145
|
+
|
|
146
|
+
// ── Icon ──
|
|
147
|
+
--hub-nav-icon-size: var(--hub-ref-icon-size, 1em);
|
|
148
|
+
--hub-nav-icon-gap: var(--hub-ref-space-2, 0.5rem);
|
|
149
|
+
|
|
150
|
+
// ── Panel mode (stacked side panels) ──
|
|
151
|
+
--hub-nav-panel-width: 16rem;
|
|
152
|
+
--hub-nav-panel-bg: var(--hub-sys-surface-elevated, #f8f9fa);
|
|
153
|
+
--hub-nav-panel-color: var(--hub-sys-text-primary, #212529);
|
|
154
|
+
--hub-nav-panel-border-color: var(--hub-sys-border-color-default, #dee2e6);
|
|
155
|
+
--hub-nav-panel-border-width: 1px;
|
|
156
|
+
--hub-nav-panel-shadow: var(--hub-sys-shadow-sm, 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075));
|
|
157
|
+
--hub-nav-panel-zindex: var(--hub-sys-zindex-dropdown, 1000);
|
|
158
|
+
// Complete `transition` value (the ds base token is already `all …`; a
|
|
159
|
+
// `transform` prefix would make the resolved declaration invalid).
|
|
160
|
+
--hub-nav-panel-transition: var(--hub-sys-transition-base, all 0.2s ease-in-out);
|
|
161
|
+
|
|
162
|
+
// ── Panel header ──
|
|
163
|
+
--hub-nav-panel-header-height: 3rem;
|
|
164
|
+
--hub-nav-panel-header-bg: var(--hub-sys-surface-page, #fff);
|
|
165
|
+
--hub-nav-panel-header-border-color: var(--hub-sys-border-color-default, #dee2e6);
|
|
166
|
+
--hub-nav-panel-header-font-size: var(--hub-ref-font-size-sm, 0.875rem);
|
|
167
|
+
--hub-nav-panel-header-font-weight: var(--hub-ref-font-weight-semibold, 600);
|
|
168
|
+
--hub-nav-panel-header-padding-x: var(--hub-ref-space-3, 1rem);
|
|
169
|
+
|
|
170
|
+
// ── Panel back button ──
|
|
171
|
+
--hub-nav-panel-back-color: var(--hub-sys-text-primary, #212529);
|
|
172
|
+
--hub-nav-panel-back-hover-bg: var(--hub-sys-state-hover-bg, rgba(0, 0, 0, 0.075));
|
|
173
|
+
--hub-nav-panel-back-size: 2rem;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ──────────────────────────────────────────────────────
|
|
177
|
+
// Semantic variant — `<hub-nav [variant]="…">`
|
|
178
|
+
// Re-bases the single `--hub-nav-accent` per variant; the hover/active
|
|
179
|
+
// affordances follow. Built-in variants pick up the exact `--hub-sys-color-*`
|
|
180
|
+
// tints; any custom variant works via the inline accent the component sets.
|
|
181
|
+
// ──────────────────────────────────────────────────────
|
|
182
|
+
|
|
183
|
+
// Open-set default — ANY variant the host application defines. The derived
|
|
184
|
+
// roles (-subtle / -emphasis / -on, plus the nav surface wash and hover tint)
|
|
185
|
+
// are re-mixed from the single `--hub-nav-accent` the component sets inline, so
|
|
186
|
+
// a custom accent (e.g. `variant="brand"` backed by `--hub-sys-color-brand`)
|
|
187
|
+
// interconnects with ONE CSS rule the user writes:
|
|
188
|
+
// :root { --hub-sys-color-brand: #ff6b00; }
|
|
189
|
+
// No per-colour CSS is needed here for custom variants — only the open default.
|
|
190
|
+
:host([data-variant]),
|
|
191
|
+
.hub-nav[data-variant] {
|
|
192
|
+
--hub-nav-accent-subtle: color-mix(in oklch, var(--hub-nav-accent) 12%, var(--hub-sys-surface-page, #ffffff));
|
|
193
|
+
--hub-nav-accent-emphasis: color-mix(in oklch, var(--hub-nav-accent) 80%, var(--hub-sys-color-ink, #212529));
|
|
194
|
+
--hub-nav-accent-on: oklch(from var(--hub-nav-accent) clamp(0, (0.62 - l) * 1000, 1) 0 h);
|
|
195
|
+
--hub-nav-bg: color-mix(in oklch, var(--hub-nav-accent) 5%, var(--hub-sys-surface-page, #fff));
|
|
196
|
+
--hub-nav-item-hover-bg: color-mix(in oklch, var(--hub-nav-accent) 8%, var(--hub-sys-surface-page, #fff));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Built-in semantic variants — re-base the single accent to the exact
|
|
200
|
+
// design-system `--hub-sys-color-<variant>` tint. The full open accent set:
|
|
201
|
+
// primary, secondary, success, danger, warning, info, neutral, light, dark.
|
|
202
|
+
$hub-nav-variants: primary, secondary, success, danger, warning, info, neutral, light, dark;
|
|
203
|
+
|
|
204
|
+
@each $variant in $hub-nav-variants {
|
|
205
|
+
:host([data-variant='#{$variant}']),
|
|
206
|
+
.hub-nav[data-variant='#{$variant}'] {
|
|
207
|
+
--hub-nav-accent: var(--hub-sys-color-#{$variant});
|
|
208
|
+
}
|
|
209
|
+
}
|