@ds-mo/ui 1.3.0 → 1.4.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.
Files changed (147) hide show
  1. package/dist/components/ds-bar-nav-action.js +1 -1
  2. package/dist/components/ds-bar-nav.js +1 -1
  3. package/dist/components/ds-bar-nav.js.map +1 -1
  4. package/dist/components/ds-breadcrumb.js +1 -1
  5. package/dist/components/ds-button-group.js +1 -1
  6. package/dist/components/ds-button.js +1 -1
  7. package/dist/components/ds-card.js +1 -1
  8. package/dist/components/ds-checkbox.js +1 -1
  9. package/dist/components/ds-chip.js +1 -1
  10. package/dist/components/ds-divider.js +1 -1
  11. package/dist/components/ds-empty-state.js +1 -1
  12. package/dist/components/ds-fade.js +1 -1
  13. package/dist/components/ds-field.js +1 -1
  14. package/dist/components/ds-header.js +1 -1
  15. package/dist/components/ds-icon.js +1 -1
  16. package/dist/components/ds-input.js +1 -1
  17. package/dist/components/ds-modal.js +1 -1
  18. package/dist/components/ds-panel-nav.js +1 -1
  19. package/dist/components/ds-panel-nav.js.map +1 -1
  20. package/dist/components/ds-radio-group.js +1 -1
  21. package/dist/components/ds-radio-group.js.map +1 -1
  22. package/dist/components/ds-scrollbar.js +1 -1
  23. package/dist/components/ds-select.js +1 -1
  24. package/dist/components/ds-surface.js +1 -1
  25. package/dist/components/ds-tab-group-nav.js +1 -1
  26. package/dist/components/ds-tab-group.js +1 -1
  27. package/dist/components/ds-table.js +1 -1
  28. package/dist/components/ds-table.js.map +1 -1
  29. package/dist/components/ds-tag.js +1 -1
  30. package/dist/components/ds-text.js +1 -1
  31. package/dist/components/ds-toast-provider.js +1 -1
  32. package/dist/components/ds-toggle-button-group.js +1 -1
  33. package/dist/components/ds-toggle-button.js +1 -1
  34. package/dist/components/ds-tooltip.js +1 -1
  35. package/dist/components/index.d.ts +3 -4
  36. package/dist/components/index.js +1 -1
  37. package/dist/components/index.js.map +1 -1
  38. package/dist/components/{p-COsKOwZR.js → p--YDw8Q4o.js} +2 -2
  39. package/dist/components/{p-OT-Q-NxH.js → p-C9za7IDu.js} +2 -2
  40. package/dist/components/p-DceSoh5V.js +2 -0
  41. package/dist/components/p-DceSoh5V.js.map +1 -0
  42. package/dist/components/{p-DrDrPeVV.js → p-DqBCQRRd.js} +2 -2
  43. package/dist/components/p-DznbYg1m.js +2 -0
  44. package/dist/components/p-DznbYg1m.js.map +1 -0
  45. package/dist/components/{p-qfvbc9w-.js → p-_LI2ymhS.js} +2 -2
  46. package/dist/components/p-_LI2ymhS.js.map +1 -0
  47. package/dist/components/{p-U1A-rprN.js → p-uMN1Ppw2.js} +2 -2
  48. package/dist/components/{p-X1N_ggsY.js → p-vW9EMP8s.js} +2 -2
  49. package/dist/types/{.stencil → components}/BarNav/BarNav.d.ts +6 -17
  50. package/dist/types/components/BarNav/bar-nav-types.d.ts +14 -0
  51. package/dist/types/{.stencil → components}/BarNav/bar-nav-utils.d.ts +1 -1
  52. package/dist/types/components/BarNav/index.d.ts +3 -0
  53. package/dist/types/{.stencil → components}/BarNavAction/BarNavAction.d.ts +1 -1
  54. package/dist/types/{.stencil → components}/PanelNav/PanelNav.d.ts +11 -26
  55. package/dist/types/components/PanelNav/index.d.ts +4 -0
  56. package/dist/types/components/PanelNav/panel-nav-types.d.ts +20 -0
  57. package/dist/types/components/PanelNav/panel-nav-utils.d.ts +26 -0
  58. package/dist/types/{.stencil → components}/TabGroupNav/TabGroupNav.d.ts +1 -1
  59. package/dist/types/components.d.ts +30 -28
  60. package/dist/types/nav/index.d.ts +5 -0
  61. package/dist/types/nav/nav-chrome.d.ts +14 -0
  62. package/dist/types/nav/shell-view-transition.d.ts +21 -0
  63. package/package.json +7 -2
  64. package/src/angular/proxies.ts +4 -4
  65. package/src/wc/components/BarNav/BarNav.tsx +18 -26
  66. package/src/wc/components/BarNav/bar-nav-types.ts +15 -0
  67. package/src/wc/components/BarNav/bar-nav-utils.ts +1 -1
  68. package/src/wc/components/BarNav/index.ts +2 -1
  69. package/src/wc/components/BarNavAction/BarNavAction.tsx +2 -1
  70. package/src/wc/components/PanelNav/PanelNav.tsx +46 -90
  71. package/src/wc/components/PanelNav/index.ts +9 -4
  72. package/src/wc/components/PanelNav/panel-nav-types.ts +22 -0
  73. package/src/wc/components/PanelNav/panel-nav-utils.ts +32 -64
  74. package/src/wc/components/TabGroupNav/TabGroupNav.tsx +8 -2
  75. package/src/wc/components.d.ts +30 -28
  76. package/src/wc/nav/index.ts +19 -0
  77. package/src/wc/nav/nav-chrome.ts +45 -0
  78. package/src/wc/nav/shell-view-transition.ts +102 -0
  79. package/dist/components/p-DOtcc9UU.js +0 -2
  80. package/dist/components/p-DOtcc9UU.js.map +0 -1
  81. package/dist/components/p-qfvbc9w-.js.map +0 -1
  82. package/dist/types/.stencil/BarNav/index.d.ts +0 -2
  83. package/dist/types/.stencil/PanelNav/index.d.ts +0 -3
  84. package/dist/types/.stencil/PanelNav/panel-nav-utils.d.ts +0 -27
  85. /package/dist/components/{p-COsKOwZR.js.map → p--YDw8Q4o.js.map} +0 -0
  86. /package/dist/components/{p-OT-Q-NxH.js.map → p-C9za7IDu.js.map} +0 -0
  87. /package/dist/components/{p-DrDrPeVV.js.map → p-DqBCQRRd.js.map} +0 -0
  88. /package/dist/components/{p-U1A-rprN.js.map → p-uMN1Ppw2.js.map} +0 -0
  89. /package/dist/components/{p-X1N_ggsY.js.map → p-vW9EMP8s.js.map} +0 -0
  90. /package/dist/types/{.stencil → components}/Accordion/Accordion.d.ts +0 -0
  91. /package/dist/types/{.stencil → components}/Badge/Badge.d.ts +0 -0
  92. /package/dist/types/{.stencil → components}/Badge/index.d.ts +0 -0
  93. /package/dist/types/{.stencil → components}/Banner/Banner.d.ts +0 -0
  94. /package/dist/types/{.stencil → components}/BarNav/bar-nav-dom-utils.d.ts +0 -0
  95. /package/dist/types/{.stencil → components}/BarNav/bar-nav-tabs-menu-utils.d.ts +0 -0
  96. /package/dist/types/{.stencil → components}/BarNavAction/index.d.ts +0 -0
  97. /package/dist/types/{.stencil → components}/Breadcrumb/Breadcrumb.d.ts +0 -0
  98. /package/dist/types/{.stencil → components}/Button/Button.d.ts +0 -0
  99. /package/dist/types/{.stencil → components}/Button/index.d.ts +0 -0
  100. /package/dist/types/{.stencil → components}/ButtonGroup/ButtonGroup.d.ts +0 -0
  101. /package/dist/types/{.stencil → components}/Card/Card.d.ts +0 -0
  102. /package/dist/types/{.stencil → components}/Checkbox/Checkbox.d.ts +0 -0
  103. /package/dist/types/{.stencil → components}/Checkbox/index.d.ts +0 -0
  104. /package/dist/types/{.stencil → components}/Chip/Chip.d.ts +0 -0
  105. /package/dist/types/{.stencil → components}/Chip/index.d.ts +0 -0
  106. /package/dist/types/{.stencil → components}/Divider/Divider.d.ts +0 -0
  107. /package/dist/types/{.stencil → components}/Divider/index.d.ts +0 -0
  108. /package/dist/types/{.stencil → components}/EmptyState/EmptyState.d.ts +0 -0
  109. /package/dist/types/{.stencil → components}/Fade/Fade.d.ts +0 -0
  110. /package/dist/types/{.stencil → components}/Fade/index.d.ts +0 -0
  111. /package/dist/types/{.stencil → components}/Field/Field.d.ts +0 -0
  112. /package/dist/types/{.stencil → components}/Header/Header.d.ts +0 -0
  113. /package/dist/types/{.stencil → components}/Icon/Icon.d.ts +0 -0
  114. /package/dist/types/{.stencil → components}/Icon/flag-icon-catalog.d.ts +0 -0
  115. /package/dist/types/{.stencil → components}/Icon/index.d.ts +0 -0
  116. /package/dist/types/{.stencil → components}/Icon/system-icon-catalog.d.ts +0 -0
  117. /package/dist/types/{.stencil → components}/Input/Input.d.ts +0 -0
  118. /package/dist/types/{.stencil → components}/Input/index.d.ts +0 -0
  119. /package/dist/types/{.stencil → components}/Loader/Loader.d.ts +0 -0
  120. /package/dist/types/{.stencil → components}/Loader/index.d.ts +0 -0
  121. /package/dist/types/{.stencil → components}/Menu/Menu.d.ts +0 -0
  122. /package/dist/types/{.stencil → components}/Modal/Modal.d.ts +0 -0
  123. /package/dist/types/{.stencil → components}/Pagination/Pagination.d.ts +0 -0
  124. /package/dist/types/{.stencil → components}/RadioGroup/RadioGroup.d.ts +0 -0
  125. /package/dist/types/{.stencil → components}/RadioGroup/index.d.ts +0 -0
  126. /package/dist/types/{.stencil → components}/Scrollbar/Scrollbar.d.ts +0 -0
  127. /package/dist/types/{.stencil → components}/Select/Select.d.ts +0 -0
  128. /package/dist/types/{.stencil → components}/Sidebar/Sidebar.d.ts +0 -0
  129. /package/dist/types/{.stencil → components}/Skeleton/Skeleton.d.ts +0 -0
  130. /package/dist/types/{.stencil → components}/Skeleton/index.d.ts +0 -0
  131. /package/dist/types/{.stencil → components}/Slider/Slider.d.ts +0 -0
  132. /package/dist/types/{.stencil → components}/Slider/index.d.ts +0 -0
  133. /package/dist/types/{.stencil → components}/Surface/Surface.d.ts +0 -0
  134. /package/dist/types/{.stencil → components}/TabGroup/TabGroup.d.ts +0 -0
  135. /package/dist/types/{.stencil → components}/TabGroup/tab-item-utils.d.ts +0 -0
  136. /package/dist/types/{.stencil → components}/Table/Table.d.ts +0 -0
  137. /package/dist/types/{.stencil → components}/Tag/Tag.d.ts +0 -0
  138. /package/dist/types/{.stencil → components}/Tag/index.d.ts +0 -0
  139. /package/dist/types/{.stencil → components}/Text/Text.d.ts +0 -0
  140. /package/dist/types/{.stencil → components}/Text/index.d.ts +0 -0
  141. /package/dist/types/{.stencil → components}/Toast/Toast.d.ts +0 -0
  142. /package/dist/types/{.stencil → components}/Toast/toast-service.d.ts +0 -0
  143. /package/dist/types/{.stencil → components}/Toggle/Toggle.d.ts +0 -0
  144. /package/dist/types/{.stencil → components}/Toggle/index.d.ts +0 -0
  145. /package/dist/types/{.stencil → components}/ToggleButton/ToggleButton.d.ts +0 -0
  146. /package/dist/types/{.stencil → components}/ToggleButtonGroup/ToggleButtonGroup.d.ts +0 -0
  147. /package/dist/types/{.stencil → components}/Tooltip/Tooltip.d.ts +0 -0
@@ -1,18 +1,22 @@
1
1
  import { Component, Prop, Event, EventEmitter, Watch, State, Element, h, Host } from '@stencil/core';
2
+ import type { NavChromeStyle } from '../../nav/nav-chrome';
3
+ import {
4
+ animateShellNavRadialReveal,
5
+ ensureShellNavVtStyle,
6
+ resolveShellNavRevealOrigin,
7
+ setShellNavRevealOriginVars,
8
+ } from '../../nav/shell-view-transition';
2
9
  import {
3
10
  deriveActiveIdFromUrl,
4
- ensurePanelNavVtStyle,
5
11
  parsePanelNavGroups,
6
12
  resolvePanelNavDisableVt,
7
- resolvePanelNavVariant,
13
+ resolvePanelNavStyle,
8
14
  shouldResyncPanelNavGroups,
9
- shouldResyncPanelNavVariant,
15
+ shouldResyncPanelNavStyle,
10
16
  } from './panel-nav-utils';
17
+ import type { PanelNavGroup, PanelNavItem, PanelNavRouterMode } from './panel-nav-types';
11
18
 
12
- // Module-level WeakMaps for per-instance VT state. Using WeakMaps instead of
13
- // class fields avoids Stencil generating getter-only property descriptors on
14
- // the host element for private fields, which throws in strict environments.
15
- // Minimal typings for the View Transitions API, which isn't in our TS lib target.
19
+ // Module-level WeakMaps
16
20
  interface ViewTransition {
17
21
  finished: Promise<void>;
18
22
  skipTransition: () => void;
@@ -24,50 +28,17 @@ type DocumentWithViewTransition = Document & {
24
28
  const vtTransitions = new WeakMap<object, ViewTransition>();
25
29
  const vtResolvers = new WeakMap<object, () => void>();
26
30
 
27
- /** Parse a CSS <time> value to milliseconds. Handles `s`, `ms`, and unitless
28
- * (assumed ms). Critically: `parseFloat('.75s')` is 0.75 — WAAPI treats that as
29
- * 0.75ms (instant/invisible), so the `s` unit must be scaled to ms. Design
30
- * tokens (e.g. `--effect-animation-duration-long-1`) are authored in seconds. */
31
- function parseCssTimeMs(value: string, fallback: number): number {
32
- const v = value.trim();
33
- const num = parseFloat(v);
34
- if (Number.isNaN(num)) return fallback;
35
- if (/ms\s*$/.test(v)) return num;
36
- if (/s\s*$/.test(v)) return num * 1000;
37
- return num;
38
- }
39
-
40
- export type PanelNavVariant = 'dashboard' | 'settings';
41
- export type PanelNavRouterMode = 'anchor' | 'event';
42
-
43
- export interface PanelNavItem {
44
- id: string;
45
- icon: string;
46
- label: string;
47
- /** Show a notification dot badge on the item */
48
- dot?: boolean;
49
- flag?: boolean;
50
- /** Route path used for `currentUrl` matching. In `anchor` mode also sets `<a href>`.
51
- * In `event` mode navigation is delegated to the host via `dsNavSelect`. */
52
- href?: string;
53
- }
54
-
55
- export interface PanelNavGroup {
56
- id?: string;
57
- label?: string;
58
- items: PanelNavItem[];
59
- }
60
-
61
31
  @Component({
62
32
  tag: 'ds-panel-nav',
63
33
  styleUrl: 'PanelNav.css',
64
34
  scoped: true,
65
35
  })
66
36
  export class PanelNav {
67
- /** Visual variant: `dashboard` = always-dark surface, `settings` = light surface */
68
- @Prop() variant: PanelNavVariant = 'dashboard';
37
+ /** Chrome style: `navigation` = navigation tokens, `default` = standard app tokens.
38
+ * Property: `navStyle`. HTML attribute: `nav-style`. */
39
+ @Prop({ attribute: 'nav-style', reflect: true }) navStyle: NavChromeStyle = 'navigation';
69
40
 
70
- /** When `true`, the component does not run its own View Transition on variant
41
+ /** When `true`, the component does not run its own View Transition on style
71
42
  * change — it just updates the rendered surface synchronously. Use this when
72
43
  * the host app orchestrates the page transition itself (e.g. Angular Router's
73
44
  * `withViewTransitions`), so the two don't fight or nest. */
@@ -122,9 +93,9 @@ export class PanelNav {
122
93
 
123
94
  @Element() el!: HTMLElement;
124
95
 
125
- /** Mirrors `variant` but is only updated inside the VT callback so the
96
+ /** Mirrors `style` but is only updated inside the VT callback so the
126
97
  * View Transition captures a clean before/after snapshot. */
127
- @State() private renderedVariant: PanelNavVariant = 'dashboard';
98
+ @State() private renderedStyle: NavChromeStyle = 'navigation';
128
99
 
129
100
  @State() private parsedGroups: PanelNavGroup[] = [];
130
101
  @State() private atBottom = false;
@@ -193,44 +164,35 @@ export class PanelNav {
193
164
  this.syncActiveFromUrl();
194
165
  }
195
166
 
196
- @Watch('variant')
197
- async onVariantChange(newVal: PanelNavVariant) {
167
+ @Watch('navStyle')
168
+ async onNavStyleChange(newVal: NavChromeStyle) {
198
169
  // Host app drives the transition (e.g. Angular Router withViewTransitions):
199
170
  // just reflect the new surface so the app's transition captures it.
200
171
  if (this.effectiveDisableViewTransition) {
201
- this.renderedVariant = newVal;
172
+ this.renderedStyle = newVal;
202
173
  return;
203
174
  }
204
175
 
205
- // Skip any in-progress transition immediately so rapid variant changes
206
- // (e.g. quick dashboard → settings → dashboard) never leave the nav stuck.
176
+ // Skip any in-progress transition immediately so rapid style changes never leave the nav stuck.
207
177
  vtTransitions.get(this)?.skipTransition();
208
178
  vtTransitions.delete(this);
209
179
 
210
180
  const doc = document as DocumentWithViewTransition;
211
181
  if (typeof doc.startViewTransition !== 'function') {
212
- this.renderedVariant = newVal;
182
+ this.renderedStyle = newVal;
213
183
  return;
214
184
  }
215
185
 
216
- ensurePanelNavVtStyle();
217
-
218
- const btn = this.el.querySelector('.panel-nav__footer-btn') as HTMLElement | null;
219
- const rect = btn?.getBoundingClientRect();
220
- const x = rect ? Math.round(rect.left + rect.width / 2) : Math.round(window.innerWidth / 2);
221
- const y = rect ? Math.round(rect.top + rect.height / 2) : Math.round(window.innerHeight / 2);
222
- const maxR = Math.ceil(Math.hypot(
223
- Math.max(x, window.innerWidth - x),
224
- Math.max(y, window.innerHeight - y),
225
- ));
226
-
227
- document.documentElement.style.setProperty('--vt-x', `${x}px`);
228
- document.documentElement.style.setProperty('--vt-y', `${y}px`);
186
+ ensureShellNavVtStyle();
187
+ const origin = resolveShellNavRevealOrigin(
188
+ this.el.querySelector('.panel-nav__footer-btn') as HTMLElement | null,
189
+ );
190
+ setShellNavRevealOriginVars(origin);
229
191
 
230
192
  const transition = doc.startViewTransition(() =>
231
193
  new Promise<void>(resolve => {
232
194
  vtResolvers.set(this, resolve);
233
- this.renderedVariant = newVal;
195
+ this.renderedStyle = newVal;
234
196
  })
235
197
  );
236
198
 
@@ -240,19 +202,13 @@ export class PanelNav {
240
202
  vtResolvers.delete(this);
241
203
  });
242
204
 
243
- transition.ready.then(() => {
244
- const durToken = getComputedStyle(document.documentElement)
245
- .getPropertyValue('--effect-animation-duration-long-1').trim();
246
- const duration = parseCssTimeMs(durToken, 750);
247
- document.documentElement.animate(
248
- { clipPath: [`circle(0px at ${x}px ${y}px)`, `circle(${maxR}px at ${x}px ${y}px)`] },
249
- { duration, easing: 'ease-in-out', fill: 'forwards', pseudoElement: '::view-transition-new(root)' },
250
- );
251
- }).catch(() => { /* transition was skipped or aborted */ });
205
+ transition.ready
206
+ .then(() => animateShellNavRadialReveal(origin))
207
+ .catch(() => { /* transition was skipped or aborted */ });
252
208
  }
253
209
 
254
210
  componentWillLoad() {
255
- this.renderedVariant = resolvePanelNavVariant(this.variant, this.el.getAttribute('variant'));
211
+ this.renderedStyle = resolvePanelNavStyle(this.navStyle, this.el.getAttribute('nav-style'));
256
212
  if (this.storageKey) {
257
213
  try {
258
214
  const stored = localStorage.getItem(this.storageKey);
@@ -331,7 +287,7 @@ export class PanelNav {
331
287
 
332
288
  /** Re-parse props assigned by the host after componentWillLoad (Angular ngAfterViewInit). */
333
289
  private syncHostPropsIfNeeded() {
334
- this.syncRenderedVariantIfNeeded();
290
+ this.syncRenderedStyleIfNeeded();
335
291
 
336
292
  if (shouldResyncPanelNavGroups(this.parsedGroups, this.groups)) {
337
293
  this.onGroupsChange(this.groups);
@@ -340,16 +296,16 @@ export class PanelNav {
340
296
  }
341
297
  }
342
298
 
343
- /** Align `renderedVariant` with `variant` when host bindings land after first paint. */
344
- private syncRenderedVariantIfNeeded() {
345
- if (!shouldResyncPanelNavVariant(this.renderedVariant, this.variant)) return;
299
+ /** Align `renderedStyle` with `style` when host bindings land after first paint. */
300
+ private syncRenderedStyleIfNeeded() {
301
+ if (!shouldResyncPanelNavStyle(this.renderedStyle, this.navStyle)) return;
346
302
 
347
303
  if (this.effectiveDisableViewTransition) {
348
304
  vtTransitions.get(this)?.skipTransition();
349
305
  vtTransitions.delete(this);
350
- this.renderedVariant = this.variant;
306
+ this.renderedStyle = this.navStyle;
351
307
  } else {
352
- void this.onVariantChange(this.variant);
308
+ void this.onNavStyleChange(this.navStyle);
353
309
  }
354
310
  }
355
311
 
@@ -546,14 +502,14 @@ export class PanelNav {
546
502
  }
547
503
 
548
504
  render() {
549
- const isDashboard = this.renderedVariant === 'dashboard';
505
+ const isNavigation = this.renderedStyle === 'navigation';
550
506
  const collapsed = this.collapsed || this.viewportNarrow;
551
507
  const { userName, userInitial } = this;
552
508
 
553
509
  const navCls: Record<string, boolean> = {
554
510
  'panel-nav': true,
555
- 'panel-nav--dashboard': isDashboard,
556
- 'panel-nav--settings': !isDashboard,
511
+ 'panel-nav--navigation': isNavigation,
512
+ 'panel-nav--default': !isNavigation,
557
513
  'panel-nav--collapsed': collapsed,
558
514
  'panel-nav--animating': this.isAnimating,
559
515
  'panel-nav--at-bottom': this.atBottom,
@@ -561,7 +517,7 @@ export class PanelNav {
561
517
 
562
518
  return (
563
519
  <Host style={{ display: 'block', position: 'relative' }}>
564
- <nav class={navCls} aria-label={isDashboard ? 'Main navigation' : 'Settings navigation'}>
520
+ <nav class={navCls} aria-label={isNavigation ? 'Main navigation' : 'Settings navigation'}>
565
521
 
566
522
  {/* ── Header: Motive logo, reveals collapse toggle on hover ── */}
567
523
  <div class="panel-nav__header">
@@ -620,15 +576,15 @@ export class PanelNav {
620
576
  visible={!this.atBottom}
621
577
  />
622
578
 
623
- {/* Left icon button — Gear in dashboard, Dashboard in settings */}
579
+ {/* Left icon button — Gear in navigation style, Dashboard in default style */}
624
580
  <button
625
581
  type="button"
626
582
  class="panel-nav__footer-btn"
627
- title={isDashboard ? 'Settings' : 'Dashboard'}
628
- aria-label={isDashboard ? 'Open settings' : 'Go to dashboard'}
583
+ title={isNavigation ? 'Settings' : 'Dashboard'}
584
+ aria-label={isNavigation ? 'Open settings' : 'Go to dashboard'}
629
585
  onClick={() => this.handleFooterAction()}
630
586
  >
631
- <ds-icon name={isDashboard ? 'Gear' : 'Dashboard'} size="md" color="inherit" />
587
+ <ds-icon name={isNavigation ? 'Gear' : 'Dashboard'} size="md" color="inherit" />
632
588
  </button>
633
589
 
634
590
  {/* Right user — label fades like nav items; right icon cross-fades chevron ↔ circle+initial */}
@@ -1,7 +1,12 @@
1
- export type { PanelNavVariant, PanelNavRouterMode, PanelNavItem, PanelNavGroup } from './PanelNav';
1
+ export type { PanelNavRouterMode, PanelNavItem, PanelNavGroup } from './panel-nav-types';
2
+ export type { NavChromeStyle } from '../../nav/nav-chrome';
2
3
  export {
3
- PANEL_NAV_VARIANT_HINT_ATTR,
4
- clearPanelNavVariantHint,
4
+ NAV_STYLE_HINT_ATTR,
5
+ setNavStyleHint,
6
+ clearNavStyleHint,
7
+ resolvePanelNavStyle,
8
+ shouldResyncPanelNavStyle,
5
9
  ensurePanelNavVtStyle,
6
- setPanelNavVariantHint,
10
+ deriveActiveIdFromUrl,
11
+ parsePanelNavGroups,
7
12
  } from './panel-nav-utils';
@@ -0,0 +1,22 @@
1
+ import type { NavChromeStyle } from '../../nav/nav-chrome';
2
+
3
+ export type { NavChromeStyle };
4
+ export type PanelNavRouterMode = 'anchor' | 'event';
5
+
6
+ export interface PanelNavItem {
7
+ id: string;
8
+ icon: string;
9
+ label: string;
10
+ /** Show a notification dot badge on the item */
11
+ dot?: boolean;
12
+ flag?: boolean;
13
+ /** Route path used for `currentUrl` matching. In `anchor` mode also sets `<a href>`.
14
+ * In `event` mode navigation is delegated to the host via `dsNavSelect`. */
15
+ href?: string;
16
+ }
17
+
18
+ export interface PanelNavGroup {
19
+ id?: string;
20
+ label?: string;
21
+ items: PanelNavItem[];
22
+ }
@@ -1,4 +1,35 @@
1
- import type { PanelNavGroup, PanelNavItem, PanelNavVariant } from './PanelNav';
1
+ import type { PanelNavGroup, PanelNavItem } from './panel-nav-types';
2
+ import {
3
+ NAV_STYLE_HINT_ATTR,
4
+ clearNavStyleHint,
5
+ readNavStyleAttr,
6
+ resolveNavChromeStyle,
7
+ setNavStyleHint,
8
+ shouldResyncNavChromeStyle,
9
+ } from '../../nav/nav-chrome';
10
+ import { ensureShellNavVtStyle } from '../../nav/shell-view-transition';
11
+
12
+ export type { NavChromeStyle } from '../../nav/nav-chrome';
13
+ export {
14
+ NAV_STYLE_HINT_ATTR,
15
+ readNavStyleAttr,
16
+ setNavStyleHint,
17
+ clearNavStyleHint,
18
+ resolveNavChromeStyle as resolvePanelNavStyle,
19
+ shouldResyncNavChromeStyle as shouldResyncPanelNavStyle,
20
+ };
21
+
22
+ /** @deprecated Use `setNavStyleHint` */
23
+ export const setPanelNavStyleHint = setNavStyleHint;
24
+
25
+ /** @deprecated Use `clearNavStyleHint` */
26
+ export const clearPanelNavStyleHint = clearNavStyleHint;
27
+
28
+ /** @deprecated Use `NAV_STYLE_HINT_ATTR` */
29
+ export const PANEL_NAV_STYLE_HINT_ATTR = NAV_STYLE_HINT_ATTR;
30
+
31
+ /** @deprecated Use `ensureShellNavVtStyle` */
32
+ export const ensurePanelNavVtStyle = ensureShellNavVtStyle;
2
33
 
3
34
  /** Whether `path` matches `href` at a segment boundary (exact or child path). */
4
35
  export function hrefMatchesPath(path: string, href: string): boolean {
@@ -42,41 +73,6 @@ export function parsePanelNavGroups(groups: string | unknown): PanelNavGroup[] {
42
73
  return [];
43
74
  }
44
75
 
45
- /** `document.documentElement` attribute for pre-bootstrap variant hints (SPA hard reload). */
46
- export const PANEL_NAV_VARIANT_HINT_ATTR = 'data-panel-nav-variant';
47
-
48
- /** Parse `variant` from a host attribute value. */
49
- export function readPanelNavVariantAttr(attr: string | null): PanelNavVariant | undefined {
50
- if (attr === 'settings' || attr === 'dashboard') return attr;
51
- return undefined;
52
- }
53
-
54
- /** Set a document-level variant hint before the custom element upgrades (hard reload). */
55
- export function setPanelNavVariantHint(variant: PanelNavVariant): void {
56
- if (typeof document === 'undefined') return;
57
- document.documentElement.setAttribute(PANEL_NAV_VARIANT_HINT_ATTR, variant);
58
- }
59
-
60
- export function clearPanelNavVariantHint(): void {
61
- if (typeof document === 'undefined') return;
62
- document.documentElement.removeAttribute(PANEL_NAV_VARIANT_HINT_ATTR);
63
- }
64
-
65
- /** Resolve initial variant — host attr, then document hint, then prop default. */
66
- export function resolvePanelNavVariant(
67
- variantProp: PanelNavVariant,
68
- variantAttr: string | null,
69
- documentVariantAttr: string | null = typeof document !== 'undefined'
70
- ? document.documentElement.getAttribute(PANEL_NAV_VARIANT_HINT_ATTR)
71
- : null,
72
- ): PanelNavVariant {
73
- return (
74
- readPanelNavVariantAttr(variantAttr) ??
75
- readPanelNavVariantAttr(documentVariantAttr) ??
76
- variantProp
77
- );
78
- }
79
-
80
76
  /** Resolve whether VT is disabled from prop and/or host attribute. */
81
77
  export function resolvePanelNavDisableVt(prop: boolean, attr: string | null): boolean {
82
78
  if (prop) return true;
@@ -84,14 +80,6 @@ export function resolvePanelNavDisableVt(prop: boolean, attr: string | null): bo
84
80
  return attr !== 'false';
85
81
  }
86
82
 
87
- /** True when internal rendered surface lags the host `variant` prop. */
88
- export function shouldResyncPanelNavVariant(
89
- renderedVariant: PanelNavVariant,
90
- variant: PanelNavVariant,
91
- ): boolean {
92
- return renderedVariant !== variant;
93
- }
94
-
95
83
  /** True when host `groups` has items but internal parsed state is still empty. */
96
84
  export function shouldResyncPanelNavGroups(
97
85
  parsedGroups: PanelNavGroup[],
@@ -102,23 +90,3 @@ export function shouldResyncPanelNavGroups(
102
90
  countPanelNavItems(parsePanelNavGroups(groups)) > 0
103
91
  );
104
92
  }
105
-
106
- let vtStyleInjected = false;
107
-
108
- /** Inject view-transition suppress styles once per document (shared by PanelNav + hosts). */
109
- export function ensurePanelNavVtStyle(): void {
110
- if (vtStyleInjected) return;
111
- const id = 'ds-panel-nav-vt-style';
112
- if (document.getElementById(id)) {
113
- vtStyleInjected = true;
114
- return;
115
- }
116
- const style = document.createElement('style');
117
- style.id = id;
118
- style.textContent = [
119
- '::view-transition-old(root),::view-transition-new(root){animation:none;mix-blend-mode:normal}',
120
- '::view-transition-new(root){clip-path:circle(0px at var(--vt-x,50%) var(--vt-y,50%))}',
121
- ].join('\n');
122
- document.head.appendChild(style);
123
- vtStyleInjected = true;
124
- }
@@ -6,7 +6,7 @@ import {
6
6
  type TabItemTab,
7
7
  } from '../TabGroup/tab-item-utils';
8
8
 
9
- export type TabGroupNavBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark';
9
+ export type TabGroupNavBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark' | 'navigation';
10
10
 
11
11
  @Component({
12
12
  tag: 'ds-tab-group-nav',
@@ -119,18 +119,24 @@ export class TabGroupNav {
119
119
  private getBgClass(): string {
120
120
  if (!this.background || this.background === 'faint') return '';
121
121
  if (this.background === 'always-dark') return 'on-always-dark';
122
+ if (this.background === 'navigation') return 'on-navigation';
122
123
  return `on-${this.background}`;
123
124
  }
124
125
 
125
126
  render() {
126
127
  const bgClass = this.getBgClass();
127
128
  const isVertical = this.orientation === 'vertical';
129
+ const isNavigation = this.background === 'navigation';
128
130
 
129
131
  return (
130
132
  <Host class="tab-group-nav-host">
131
133
  <div
132
134
  role="tablist"
133
- class={{ 'tab-list': true, 'tab-list--vertical': isVertical }}
135
+ class={{
136
+ 'tab-list': true,
137
+ 'tab-list--vertical': isVertical,
138
+ 'tab-list--on-navigation': isNavigation,
139
+ }}
134
140
  aria-label={this.ariaLabel}
135
141
  aria-labelledby={this.ariaLabelledby}
136
142
  aria-orientation={isVertical ? 'vertical' : undefined}
@@ -8,7 +8,8 @@ import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
8
8
  import { AccordionItemData } from "./components/Accordion/Accordion";
9
9
  import { BadgeSurface, BadgeVariant } from "./components/Badge/Badge";
10
10
  import { BannerContrast, BannerIntent } from "./components/Banner/Banner";
11
- import { BarNavActionItem, BarNavBackground, BarNavTab } from "./components/BarNav/BarNav";
11
+ import { BarNavActionItem, BarNavTab } from "./components/BarNav/bar-nav-types";
12
+ import { NavChromeStyle } from "./nav/nav-chrome";
12
13
  import { BarNavActionBackground } from "./components/BarNavAction/BarNavAction";
13
14
  import { BreadcrumbItem } from "./components/Breadcrumb/Breadcrumb";
14
15
  import { ButtonBackground, ButtonContrast, ButtonElevation, ButtonIntent, ButtonSize, ButtonVariant } from "./components/Button/Button";
@@ -23,7 +24,7 @@ import { IconColor, IconSize } from "./components/Icon/Icon";
23
24
  import { InputType } from "./components/Input/Input";
24
25
  import { MenuAlign, MenuItemData, MenuSection, MenuSide } from "./components/Menu/Menu";
25
26
  import { ModalWidth } from "./components/Modal/Modal";
26
- import { PanelNavGroup, PanelNavRouterMode, PanelNavVariant } from "./components/PanelNav/PanelNav";
27
+ import { PanelNavGroup, PanelNavRouterMode } from "./components/PanelNav/panel-nav-types";
27
28
  import { RadioOption } from "./components/RadioGroup/RadioGroup";
28
29
  import { ScrollbarVariant } from "./components/Scrollbar/Scrollbar";
29
30
  import { SelectOption } from "./components/Select/Select";
@@ -43,7 +44,8 @@ import { TooltipAlign, TooltipSide } from "./components/Tooltip/Tooltip";
43
44
  export { AccordionItemData } from "./components/Accordion/Accordion";
44
45
  export { BadgeSurface, BadgeVariant } from "./components/Badge/Badge";
45
46
  export { BannerContrast, BannerIntent } from "./components/Banner/Banner";
46
- export { BarNavActionItem, BarNavBackground, BarNavTab } from "./components/BarNav/BarNav";
47
+ export { BarNavActionItem, BarNavTab } from "./components/BarNav/bar-nav-types";
48
+ export { NavChromeStyle } from "./nav/nav-chrome";
47
49
  export { BarNavActionBackground } from "./components/BarNavAction/BarNavAction";
48
50
  export { BreadcrumbItem } from "./components/Breadcrumb/Breadcrumb";
49
51
  export { ButtonBackground, ButtonContrast, ButtonElevation, ButtonIntent, ButtonSize, ButtonVariant } from "./components/Button/Button";
@@ -58,7 +60,7 @@ export { IconColor, IconSize } from "./components/Icon/Icon";
58
60
  export { InputType } from "./components/Input/Input";
59
61
  export { MenuAlign, MenuItemData, MenuSection, MenuSide } from "./components/Menu/Menu";
60
62
  export { ModalWidth } from "./components/Modal/Modal";
61
- export { PanelNavGroup, PanelNavRouterMode, PanelNavVariant } from "./components/PanelNav/PanelNav";
63
+ export { PanelNavGroup, PanelNavRouterMode } from "./components/PanelNav/panel-nav-types";
62
64
  export { RadioOption } from "./components/RadioGroup/RadioGroup";
63
65
  export { ScrollbarVariant } from "./components/Scrollbar/Scrollbar";
64
66
  export { SelectOption } from "./components/Select/Select";
@@ -169,11 +171,6 @@ export namespace Components {
169
171
  * @default ''
170
172
  */
171
173
  "actionsJson": string;
172
- /**
173
- * Surface background variant.
174
- * @default 'secondary'
175
- */
176
- "background": BarNavBackground;
177
174
  /**
178
175
  * Section base path (e.g. `/dashboard/safety`). Used with `currentUrl` to derive `value`.
179
176
  * @default ''
@@ -188,6 +185,11 @@ export namespace Components {
188
185
  * Fallback heading shown when no tabs are provided. When tabs are present the heading is hidden.
189
186
  */
190
187
  "heading": string | undefined;
188
+ /**
189
+ * Chrome style: `navigation` = navigation tokens, `default` = app tokens. Property: `navStyle`. HTML attribute: `nav-style`.
190
+ * @default 'default'
191
+ */
192
+ "navStyle": NavChromeStyle;
191
193
  /**
192
194
  * Tab items for the left section. Set via JS property: `el.tabs = [...]`. Replace the array reference to update.
193
195
  * @default []
@@ -619,7 +621,7 @@ export namespace Components {
619
621
  */
620
622
  "currentUrl": string;
621
623
  /**
622
- * When `true`, the component does not run its own View Transition on variant change — it just updates the rendered surface synchronously. Use this when the host app orchestrates the page transition itself (e.g. Angular Router's `withViewTransitions`), so the two don't fight or nest.
624
+ * When `true`, the component does not run its own View Transition on style change — it just updates the rendered surface synchronously. Use this when the host app orchestrates the page transition itself (e.g. Angular Router's `withViewTransitions`), so the two don't fight or nest.
623
625
  * @default false
624
626
  */
625
627
  "disableViewTransition": boolean;
@@ -628,6 +630,11 @@ export namespace Components {
628
630
  * @default '[]'
629
631
  */
630
632
  "groups": string | PanelNavGroup[];
633
+ /**
634
+ * Chrome style: `navigation` = navigation tokens, `default` = standard app tokens. Property: `navStyle`. HTML attribute: `nav-style`.
635
+ * @default 'navigation'
636
+ */
637
+ "navStyle": NavChromeStyle;
631
638
  /**
632
639
  * How items with `href` render: - `anchor` (default): native `<a href>` — works with routers that intercept anchors. - `event`: always `<button>`; host handles navigation via `dsNavSelect`.
633
640
  * @default 'anchor'
@@ -648,11 +655,6 @@ export namespace Components {
648
655
  * @default ''
649
656
  */
650
657
  "userName": string;
651
- /**
652
- * Visual variant: `dashboard` = always-dark surface, `settings` = light surface
653
- * @default 'dashboard'
654
- */
655
- "variant": PanelNavVariant;
656
658
  }
657
659
  interface DsRadioGroup {
658
660
  "ariaLabel": string | undefined;
@@ -1808,11 +1810,6 @@ declare namespace LocalJSX {
1808
1810
  * @default ''
1809
1811
  */
1810
1812
  "actionsJson"?: string;
1811
- /**
1812
- * Surface background variant.
1813
- * @default 'secondary'
1814
- */
1815
- "background"?: BarNavBackground;
1816
1813
  /**
1817
1814
  * Section base path (e.g. `/dashboard/safety`). Used with `currentUrl` to derive `value`.
1818
1815
  * @default ''
@@ -1827,6 +1824,11 @@ declare namespace LocalJSX {
1827
1824
  * Fallback heading shown when no tabs are provided. When tabs are present the heading is hidden.
1828
1825
  */
1829
1826
  "heading"?: string | undefined;
1827
+ /**
1828
+ * Chrome style: `navigation` = navigation tokens, `default` = app tokens. Property: `navStyle`. HTML attribute: `nav-style`.
1829
+ * @default 'default'
1830
+ */
1831
+ "navStyle"?: NavChromeStyle;
1830
1832
  /**
1831
1833
  * Emitted when an action button is toggled. Detail = { id, selected }.
1832
1834
  */
@@ -2296,7 +2298,7 @@ declare namespace LocalJSX {
2296
2298
  */
2297
2299
  "currentUrl"?: string;
2298
2300
  /**
2299
- * When `true`, the component does not run its own View Transition on variant change — it just updates the rendered surface synchronously. Use this when the host app orchestrates the page transition itself (e.g. Angular Router's `withViewTransitions`), so the two don't fight or nest.
2301
+ * When `true`, the component does not run its own View Transition on style change — it just updates the rendered surface synchronously. Use this when the host app orchestrates the page transition itself (e.g. Angular Router's `withViewTransitions`), so the two don't fight or nest.
2300
2302
  * @default false
2301
2303
  */
2302
2304
  "disableViewTransition"?: boolean;
@@ -2305,6 +2307,11 @@ declare namespace LocalJSX {
2305
2307
  * @default '[]'
2306
2308
  */
2307
2309
  "groups"?: string | PanelNavGroup[];
2310
+ /**
2311
+ * Chrome style: `navigation` = navigation tokens, `default` = standard app tokens. Property: `navStyle`. HTML attribute: `nav-style`.
2312
+ * @default 'navigation'
2313
+ */
2314
+ "navStyle"?: NavChromeStyle;
2308
2315
  /**
2309
2316
  * Emitted when the footer left button (gear / dashboard) is clicked.
2310
2317
  */
@@ -2341,11 +2348,6 @@ declare namespace LocalJSX {
2341
2348
  * @default ''
2342
2349
  */
2343
2350
  "userName"?: string;
2344
- /**
2345
- * Visual variant: `dashboard` = always-dark surface, `settings` = light surface
2346
- * @default 'dashboard'
2347
- */
2348
- "variant"?: PanelNavVariant;
2349
2351
  }
2350
2352
  interface DsRadioGroup {
2351
2353
  "ariaLabel"?: string | undefined;
@@ -2795,7 +2797,7 @@ declare namespace LocalJSX {
2795
2797
  "value": string;
2796
2798
  "actionsJson": string;
2797
2799
  "heading": string | undefined;
2798
- "background": BarNavBackground;
2800
+ "navStyle": NavChromeStyle;
2799
2801
  "basePath": string;
2800
2802
  "currentUrl": string;
2801
2803
  }
@@ -2933,7 +2935,7 @@ declare namespace LocalJSX {
2933
2935
  "inactive": boolean;
2934
2936
  }
2935
2937
  interface DsPanelNavAttributes {
2936
- "variant": PanelNavVariant;
2938
+ "navStyle": NavChromeStyle;
2937
2939
  "disableViewTransition": boolean;
2938
2940
  "groups": string | PanelNavGroup[];
2939
2941
  "routerMode": PanelNavRouterMode;
@@ -0,0 +1,19 @@
1
+ export type { NavChromeStyle } from './nav-chrome';
2
+ export {
3
+ NAV_STYLE_HINT_ATTR,
4
+ readNavStyleAttr,
5
+ setNavStyleHint,
6
+ clearNavStyleHint,
7
+ resolveNavChromeStyle,
8
+ shouldResyncNavChromeStyle,
9
+ } from './nav-chrome';
10
+ export {
11
+ SHELL_BAR_NAV_VT_NAME,
12
+ parseCssTimeMs,
13
+ ensureShellNavVtStyle,
14
+ resolveShellNavRevealOrigin,
15
+ setShellNavRevealOriginVars,
16
+ animateShellNavRadialReveal,
17
+ runShellNavStyleRevealOnReady,
18
+ } from './shell-view-transition';
19
+ export type { ShellNavRevealOrigin } from './shell-view-transition';