@ds-mo/ui 1.8.1 → 1.9.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 (79) hide show
  1. package/dist/.build-stamp +1 -1
  2. package/dist/components/ds-app-shell.js +1 -1
  3. package/dist/components/ds-app-shell.js.map +1 -1
  4. package/dist/components/ds-badge.js +1 -1
  5. package/dist/components/ds-banner.js +1 -1
  6. package/dist/components/ds-bar-nav-action.js +1 -1
  7. package/dist/components/ds-bar-nav.js +1 -1
  8. package/dist/components/ds-bar-nav.js.map +1 -1
  9. package/dist/components/ds-fade.js +1 -1
  10. package/dist/components/ds-fade.js.map +1 -1
  11. package/dist/components/ds-menu.js +1 -1
  12. package/dist/components/ds-modal.js +1 -1
  13. package/dist/components/ds-panel-nav.js +1 -1
  14. package/dist/components/ds-panel-nav.js.map +1 -1
  15. package/dist/components/ds-panel-tools.js +1 -1
  16. package/dist/components/ds-panel-tools.js.map +1 -1
  17. package/dist/components/ds-select.js +1 -1
  18. package/dist/components/ds-slider.js +1 -1
  19. package/dist/components/ds-slider.js.map +1 -1
  20. package/dist/components/ds-tab-group-nav.js +1 -1
  21. package/dist/components/ds-tab-group.js +1 -1
  22. package/dist/components/ds-toast-provider.js +1 -1
  23. package/dist/components/ds-toggle.js +1 -1
  24. package/dist/components/ds-tooltip.js +1 -1
  25. package/dist/components/{p-BvmooLHV.js → p-C1cBr-Ri.js} +2 -2
  26. package/dist/components/{p-DrvpsLK6.js → p-CCZFMcLe.js} +2 -2
  27. package/dist/components/p-CiEc8Nwx.js +2 -0
  28. package/dist/components/p-CiEc8Nwx.js.map +1 -0
  29. package/dist/components/{p-C4VSrrAB.js → p-CuuuDjJJ.js} +2 -2
  30. package/dist/components/p-Dl1GvZQ2.js +2 -0
  31. package/dist/components/p-Dl1GvZQ2.js.map +1 -0
  32. package/dist/components/{p-DZDXwEMg.js → p-DlsexsFg.js} +2 -2
  33. package/dist/components/p-g6MCxfm4.js +2 -0
  34. package/dist/components/p-g6MCxfm4.js.map +1 -0
  35. package/dist/types/components/AppShell/AppShell.d.ts +7 -5
  36. package/dist/types/components/BarNav/BarNav.d.ts +2 -4
  37. package/dist/types/components/PanelNav/PanelNav.d.ts +4 -13
  38. package/dist/types/components/PanelNav/index.d.ts +1 -1
  39. package/dist/types/components/PanelNav/panel-nav-utils.d.ts +0 -9
  40. package/dist/types/components/PanelTools/PanelTools.d.ts +29 -11
  41. package/dist/types/components/PanelTools/index.d.ts +2 -2
  42. package/dist/types/components/PanelTools/panel-tools-types.d.ts +15 -2
  43. package/dist/types/components/PanelTools/panel-tools-utils.d.ts +4 -0
  44. package/dist/types/components.d.ts +67 -21
  45. package/dist/types/nav/badge-gradient-ring.d.ts +1 -1
  46. package/dist/types/nav/index.d.ts +1 -1
  47. package/dist/types/nav/nav-chrome.d.ts +4 -8
  48. package/dist/types/nav/shell-gradient.d.ts +6 -3
  49. package/package.json +1 -1
  50. package/src/angular/proxies.ts +12 -3
  51. package/src/react/ds-panel-tools.ts +4 -3
  52. package/src/wc/components/AppShell/AppShell.tsx +54 -38
  53. package/src/wc/components/Badge/Badge.tsx +3 -12
  54. package/src/wc/components/BarNav/BarNav.tsx +6 -18
  55. package/src/wc/components/PanelNav/PanelNav.tsx +23 -103
  56. package/src/wc/components/PanelNav/index.ts +0 -1
  57. package/src/wc/components/PanelNav/panel-nav-utils.ts +0 -13
  58. package/src/wc/components/PanelTools/PanelTools.tsx +162 -80
  59. package/src/wc/components/PanelTools/index.ts +6 -2
  60. package/src/wc/components/PanelTools/panel-tools-types.ts +18 -3
  61. package/src/wc/components/PanelTools/panel-tools-utils.ts +31 -0
  62. package/src/wc/components.d.ts +67 -21
  63. package/src/wc/nav/badge-gradient-ring.ts +3 -8
  64. package/src/wc/nav/index.ts +3 -1
  65. package/src/wc/nav/nav-chrome.ts +19 -17
  66. package/src/wc/nav/shell-gradient.ts +9 -4
  67. package/src/wc/nav/shell-view-transition.ts +13 -6
  68. package/dist/components/p-B8VZmH43.js +0 -2
  69. package/dist/components/p-B8VZmH43.js.map +0 -1
  70. package/dist/components/p-BucV1U6A.js +0 -2
  71. package/dist/components/p-BucV1U6A.js.map +0 -1
  72. package/dist/components/p-CX7-_qOW.js +0 -2
  73. package/dist/components/p-CX7-_qOW.js.map +0 -1
  74. package/dist/components/p-TtnqbcnR.js +0 -2
  75. package/dist/components/p-TtnqbcnR.js.map +0 -1
  76. /package/dist/components/{p-BvmooLHV.js.map → p-C1cBr-Ri.js.map} +0 -0
  77. /package/dist/components/{p-DrvpsLK6.js.map → p-CCZFMcLe.js.map} +0 -0
  78. /package/dist/components/{p-C4VSrrAB.js.map → p-CuuuDjJJ.js.map} +0 -0
  79. /package/dist/components/{p-DZDXwEMg.js.map → p-DlsexsFg.js.map} +0 -0
@@ -7,7 +7,7 @@ import {
7
7
  SHELL_GRADIENT_POSITION_BAR_VAR,
8
8
  SHELL_GRADIENT_POSITION_PANEL_VAR,
9
9
  SHELL_GRADIENT_SIZE_VAR,
10
- shellGradientImageForStyle,
10
+ buildShellRadialGradient,
11
11
  shellGradientPositionBar,
12
12
  shellGradientPositionPanel,
13
13
  shellGradientSize,
@@ -20,9 +20,9 @@ import {
20
20
  })
21
21
  export class AppShell {
22
22
  /** Chrome style propagated to slotted `ds-panel-nav` and `ds-bar-nav`. */
23
- @Prop({ attribute: 'nav-style', reflect: true }) navStyle: NavChromeStyle = 'navigation';
23
+ @Prop({ attribute: 'nav-style', reflect: true }) navStyle: NavChromeStyle = 'dashboard';
24
24
 
25
- /** When `true`, paints the shared L-shaped radial wash on panel + bar backgrounds. */
25
+ /** When `true`, paints the shared chrome surface (bg + wash + grid) behind panel, bar, and tools. */
26
26
  @Prop({ reflect: true }) gradient: boolean = false;
27
27
 
28
28
  /**
@@ -38,12 +38,12 @@ export class AppShell {
38
38
  componentDidLoad() {
39
39
  this.syncSlottedNavStyle();
40
40
  this.connectMetricsObserver();
41
- this.scheduleGradientVars();
41
+ this.scheduleChromeSync();
42
42
  }
43
43
 
44
- private scheduleGradientVars() {
45
- this.updateGradientVars();
46
- requestAnimationFrame(() => this.updateGradientVars());
44
+ private scheduleChromeSync() {
45
+ this.syncChrome();
46
+ requestAnimationFrame(() => this.syncChrome());
47
47
  }
48
48
 
49
49
  disconnectedCallback() {
@@ -56,17 +56,28 @@ export class AppShell {
56
56
  @Watch('gradientSrc')
57
57
  onShellPropsChange() {
58
58
  this.syncSlottedNavStyle();
59
- this.scheduleGradientVars();
59
+ this.scheduleChromeSync();
60
+ }
61
+
62
+ private syncSlottedNavStyle() {
63
+ const panel = this.el.querySelector('ds-panel-nav') as (HTMLElement & { navStyle: NavChromeStyle }) | null;
64
+ const bar = this.el.querySelector('ds-bar-nav') as (HTMLElement & { navStyle: NavChromeStyle }) | null;
65
+ if (panel) {
66
+ panel.setAttribute('nav-style', this.navStyle);
67
+ panel.navStyle = this.navStyle;
68
+ }
69
+ if (bar) {
70
+ bar.setAttribute('nav-style', this.navStyle);
71
+ bar.navStyle = this.navStyle;
72
+ }
60
73
  }
61
74
 
62
75
  private connectMetricsObserver() {
63
- this.resizeObserver = new ResizeObserver(() => this.scheduleGradientVars());
76
+ this.resizeObserver = new ResizeObserver(() => this.scheduleChromeSync());
64
77
  this.resizeObserver.observe(this.el);
65
78
  const panelWrap = this.el.querySelector('.app-shell__panel');
66
- const barWrap = this.el.querySelector('.app-shell__bar');
67
79
  if (panelWrap) this.resizeObserver.observe(panelWrap);
68
- if (barWrap) this.resizeObserver.observe(barWrap);
69
- this.scheduleGradientVars();
80
+ this.scheduleChromeSync();
70
81
  }
71
82
 
72
83
  private applyGradientVars(target: HTMLElement, vars: Record<string, string | null>) {
@@ -77,12 +88,10 @@ export class AppShell {
77
88
  }
78
89
  }
79
90
 
80
- private clearGradientVars(targets: HTMLElement[]) {
91
+ private clearGradientPaintVars(targets: HTMLElement[]) {
81
92
  const keys = [
82
93
  SHELL_GRADIENT_IMAGE_VAR,
83
94
  SHELL_GRADIENT_SIZE_VAR,
84
- SHELL_GRADIENT_POSITION_PANEL_VAR,
85
- SHELL_GRADIENT_POSITION_BAR_VAR,
86
95
  SHELL_GRADIENT_OPACITY_VAR,
87
96
  ];
88
97
  for (const target of targets) {
@@ -90,44 +99,49 @@ export class AppShell {
90
99
  }
91
100
  }
92
101
 
93
- private syncSlottedNavStyle() {
94
- const panel = this.el.querySelector('ds-panel-nav') as (HTMLElement & { navStyle: NavChromeStyle }) | null;
95
- const bar = this.el.querySelector('ds-bar-nav') as (HTMLElement & { navStyle: NavChromeStyle }) | null;
102
+ /** Panel/bar wash offsets for scroll fades and badge rings. */
103
+ private syncChromeLayoutVars(
104
+ panel: HTMLElement | null,
105
+ bar: HTMLElement | null,
106
+ panelPosition: string,
107
+ barPosition: string,
108
+ ) {
96
109
  if (panel) {
97
- panel.setAttribute('nav-style', this.navStyle);
98
- panel.navStyle = this.navStyle;
110
+ panel.style.setProperty(SHELL_GRADIENT_POSITION_PANEL_VAR, panelPosition);
99
111
  }
100
112
  if (bar) {
101
- bar.setAttribute('nav-style', this.navStyle);
102
- bar.navStyle = this.navStyle;
113
+ bar.style.setProperty(SHELL_GRADIENT_POSITION_BAR_VAR, barPosition);
103
114
  }
104
115
  }
105
116
 
106
- private updateGradientVars() {
117
+ private syncChrome() {
107
118
  const panel = this.el.querySelector('ds-panel-nav') as HTMLElement | null;
108
119
  const bar = this.el.querySelector('ds-bar-nav') as HTMLElement | null;
109
120
  const targets = [this.el, panel, bar].filter((el): el is HTMLElement => el !== null);
110
121
 
122
+ const shellRect = this.el.getBoundingClientRect();
123
+ const panelWrap = this.el.querySelector('.app-shell__panel') as HTMLElement | null;
124
+ const panelWidth = panelWrap?.getBoundingClientRect().width ?? 0;
125
+
126
+ const panelPosition = shellGradientPositionPanel();
127
+ const barPosition = shellGradientPositionBar(panelWidth);
128
+
129
+ this.syncChromeLayoutVars(panel, bar, panelPosition, barPosition);
130
+
111
131
  if (!this.gradient) {
112
- this.clearGradientVars(targets);
132
+ this.clearGradientPaintVars(targets);
113
133
  return;
114
134
  }
115
135
 
116
136
  const image = this.gradientSrc.trim()
117
137
  ? `url(${this.gradientSrc.trim()})`
118
- : shellGradientImageForStyle(this.navStyle);
119
-
120
- const shellRect = this.el.getBoundingClientRect();
121
- const panelWrap = this.el.querySelector('.app-shell__panel') as HTMLElement | null;
122
- const panelWidth = panelWrap?.getBoundingClientRect().width ?? 0;
138
+ : buildShellRadialGradient();
123
139
 
124
140
  const size = shellGradientSize({
125
141
  width: shellRect.width,
126
142
  height: shellRect.height,
127
143
  panelWidth,
128
144
  });
129
- const panelPosition = shellGradientPositionPanel();
130
- const barPosition = shellGradientPositionBar(panelWidth);
131
145
  const opacity = SHELL_GRADIENT_OPACITY;
132
146
 
133
147
  for (const target of targets) {
@@ -157,25 +171,27 @@ export class AppShell {
157
171
  const shellCls: Record<string, boolean> = {
158
172
  'app-shell': true,
159
173
  'app-shell--gradient': this.gradient,
174
+ [`app-shell--${this.navStyle}`]: true,
160
175
  };
161
176
 
162
177
  return (
163
178
  <Host class={shellCls}>
164
179
  <div class="app-shell__row">
180
+ {this.gradient ? <div class="app-shell__chrome" aria-hidden="true" /> : null}
165
181
  <div class="app-shell__panel">
166
182
  <slot name="panel" />
167
183
  </div>
168
184
  <div class="app-shell__main">
169
- <div class="app-shell__bar">
170
- <slot name="bar" />
171
- </div>
172
- <div class="app-shell__workspace">
185
+ <div class="app-shell__stack">
186
+ <div class="app-shell__bar">
187
+ <slot name="bar" />
188
+ </div>
173
189
  <div class="app-shell__content">
174
190
  <slot />
175
191
  </div>
176
- <div class="app-shell__tools">
177
- <slot name="tools" />
178
- </div>
192
+ </div>
193
+ <div class="app-shell__tools">
194
+ <slot name="tools" />
179
195
  </div>
180
196
  </div>
181
197
  </div>
@@ -1,10 +1,7 @@
1
1
  import { Component, Prop, Element, State, Watch, h, Host } from '@stencil/core';
2
2
  import {
3
3
  BADGE_GRADIENT_POSITION_VAR,
4
- badgeGradientPosition,
5
- findGradientSurface,
6
4
  isShellGradientActive,
7
- readShellGradientPosition,
8
5
  } from '../../nav/badge-gradient-ring';
9
6
 
10
7
  export type BadgeVariant = 'counter' | 'dot';
@@ -137,16 +134,10 @@ export class Badge {
137
134
  void this.gradientLayoutVersion;
138
135
 
139
136
  const style: Record<string, string> = { '--_badge-ring': ring };
140
- if (!this.gradientBackground) return style;
137
+ if (!this.gradientBackground || !isShellGradientActive(this.el)) return style;
141
138
 
142
- const surface = findGradientSurface(this.el);
143
- if (!surface) return style;
144
-
145
- style[BADGE_GRADIENT_POSITION_VAR] = badgeGradientPosition(
146
- this.el,
147
- surface,
148
- readShellGradientPosition(surface),
149
- );
139
+ /* Shell chrome wash uses background-attachment: fixed at viewport origin. */
140
+ style[BADGE_GRADIENT_POSITION_VAR] = '0 0';
150
141
  return style;
151
142
  }
152
143
 
@@ -9,10 +9,8 @@ import {
9
9
  h,
10
10
  Host,
11
11
  } from '@stencil/core';
12
- import type { MenuItemData } from '../Menu/menu-types';
13
- import type { BarNavActionBackground } from '../BarNavAction/BarNavAction';
14
12
  import type { NavChromeStyle } from '../../nav/nav-chrome';
15
- import { SHELL_BAR_NAV_VT_NAME } from '../../nav/shell-view-transition';
13
+ import type { MenuItemData } from '../Menu/menu-types';
16
14
  import type { BarNavActionItem, BarNavTab } from './bar-nav-types';
17
15
  import {
18
16
  deriveBarNavValueFromUrl,
@@ -37,6 +35,9 @@ import {
37
35
  scoped: true,
38
36
  })
39
37
  export class BarNav {
38
+ /** Style slot: `dashboard` or `settings`. Colors match for now. */
39
+ @Prop({ attribute: 'nav-style', reflect: true }) navStyle: NavChromeStyle = 'dashboard';
40
+
40
41
  @Element() el!: HTMLElement;
41
42
 
42
43
  /**
@@ -66,10 +67,6 @@ export class BarNav {
66
67
  */
67
68
  @Prop() heading: string | undefined;
68
69
 
69
- /** Chrome style: `navigation` = navigation tokens, `default` = app tokens.
70
- * Property: `navStyle`. HTML attribute: `nav-style`. */
71
- @Prop({ attribute: 'nav-style', reflect: true }) navStyle: NavChromeStyle = 'default';
72
-
73
70
  /** Section base path (e.g. `/dashboard/safety`). Used with `currentUrl` to derive `value`. */
74
71
  @Prop() basePath: string = '';
75
72
 
@@ -494,16 +491,11 @@ export class BarNav {
494
491
  }
495
492
  }
496
493
 
497
- private get tabSurface(): BarNavActionBackground | undefined {
498
- return this.navStyle === 'navigation' ? 'navigation' : undefined;
499
- }
500
-
501
494
  render() {
502
495
  const sectionReady =
503
496
  this.basePath !== '' && this.committedSection === this.basePath;
504
497
  const hasTabs =
505
498
  sectionReady && this.resolvedTabs.length > 0 && !this.hideTabsForDetailRoute;
506
- const tabSurface = this.tabSurface;
507
499
  const tabGroupKey = this.basePath || 'no-section';
508
500
 
509
501
  return (
@@ -511,11 +503,10 @@ export class BarNav {
511
503
  <header
512
504
  class={{
513
505
  'bar-nav': true,
514
- 'bar-nav--navigation': this.navStyle === 'navigation',
515
- 'bar-nav--default': this.navStyle === 'default',
506
+ 'bar-nav--dashboard': this.navStyle === 'dashboard',
507
+ 'bar-nav--settings': this.navStyle === 'settings',
516
508
  'bar-nav--tabs-collapsed': hasTabs && this.tabsCollapsed,
517
509
  }}
518
- style={{ viewTransitionName: SHELL_BAR_NAV_VT_NAME }}
519
510
  ref={el => {
520
511
  this.headerEl = el as HTMLElement;
521
512
  if (el && !this.resizeObserver) {
@@ -536,7 +527,6 @@ export class BarNav {
536
527
  }}
537
528
  tabs={this.resolvedTabs}
538
529
  value={this.effectiveValue}
539
- background={tabSurface}
540
530
  />
541
531
  </div>
542
532
  )}
@@ -551,7 +541,6 @@ export class BarNav {
551
541
  }}
552
542
  tabs={this.resolvedTabs}
553
543
  value={this.effectiveValue}
554
- background={tabSurface}
555
544
  onDsChange={(e: Event) => this.handleTabChange(e)}
556
545
  />
557
546
  </div>
@@ -634,7 +623,6 @@ export class BarNav {
634
623
  dot={action.dot ?? false}
635
624
  inactive={action.inactive}
636
625
  aria-label={action.ariaLabel ?? action.id}
637
- background={tabSurface}
638
626
  onDsChange={(e: Event) => this.handleActionChange(action.id, e)}
639
627
  />
640
628
  ))}
@@ -1,11 +1,5 @@
1
1
  import { Component, Prop, Event, EventEmitter, Watch, State, Element, h, Host } from '@stencil/core';
2
2
  import type { NavChromeStyle } from '../../nav/nav-chrome';
3
- import {
4
- animateShellNavRadialReveal,
5
- ensureShellNavVtStyle,
6
- resolveShellNavRevealOrigin,
7
- setShellNavRevealOriginVars,
8
- } from '../../nav/shell-view-transition';
9
3
  import {
10
4
  deriveActiveIdFromUrl,
11
5
  parsePanelNavGroups,
@@ -22,18 +16,6 @@ import {
22
16
  type PanelNavUserActionDetail,
23
17
  } from './panel-nav-types';
24
18
 
25
- // Module-level WeakMaps
26
- interface ViewTransition {
27
- finished: Promise<void>;
28
- skipTransition: () => void;
29
- }
30
- type DocumentWithViewTransition = Document & {
31
- startViewTransition?: (callback: () => void | Promise<void>) => ViewTransition;
32
- };
33
-
34
- const vtTransitions = new WeakMap<object, ViewTransition>();
35
- const vtResolvers = new WeakMap<object, () => void>();
36
-
37
19
  @Component({
38
20
  tag: 'ds-panel-nav',
39
21
  styleUrl: 'PanelNav.css',
@@ -41,14 +23,11 @@ const vtResolvers = new WeakMap<object, () => void>();
41
23
  scoped: true,
42
24
  })
43
25
  export class PanelNav {
44
- /** Chrome style: `navigation` = navigation tokens, `default` = standard app tokens.
45
- * Property: `navStyle`. HTML attribute: `nav-style`. */
46
- @Prop({ attribute: 'nav-style', reflect: true }) navStyle: NavChromeStyle = 'navigation';
47
-
48
- /** When `true`, the component does not run its own View Transition on style
49
- * change — it just updates the rendered surface synchronously. Use this when
50
- * the host app orchestrates the page transition itself (e.g. Angular Router's
51
- * `withViewTransitions`), so the two don't fight or nest. */
26
+ /** Style slot: `dashboard` or `settings`. Colors match for now;
27
+ * class hooks reserved for texture/glyph layers. Property: `navStyle`. Attribute: `nav-style`. */
28
+ @Prop({ attribute: 'nav-style', reflect: true }) navStyle: NavChromeStyle = 'dashboard';
29
+
30
+ /** When `true`, style changes apply synchronously host app owns view transitions. */
52
31
  @Prop() disableViewTransition: boolean = false;
53
32
 
54
33
  /** Nav groups — set via JS property (`el.groups = [...]`) or JSON string attribute. */
@@ -98,10 +77,7 @@ export class PanelNav {
98
77
 
99
78
  @Element() el!: HTMLElement;
100
79
 
101
- /** Mirrors `style` but is only updated inside the VT callback so the
102
- * View Transition captures a clean before/after snapshot. */
103
- @State() private renderedStyle: NavChromeStyle = 'navigation';
104
-
80
+ @State() private renderedStyle: NavChromeStyle = 'dashboard';
105
81
  @State() private parsedGroups: PanelNavGroup[] = [];
106
82
  @State() private atBottom = false;
107
83
  @State() private isAnimating = false;
@@ -131,7 +107,6 @@ export class PanelNav {
131
107
  return this.urlDerivedActiveId || this.activeId;
132
108
  }
133
109
 
134
- /** Host may set `disable-view-transition` as an attribute before the JS prop lands. */
135
110
  private get effectiveDisableViewTransition(): boolean {
136
111
  return resolvePanelNavDisableVt(
137
112
  this.disableViewTransition,
@@ -170,46 +145,8 @@ export class PanelNav {
170
145
  }
171
146
 
172
147
  @Watch('navStyle')
173
- async onNavStyleChange(newVal: NavChromeStyle) {
174
- // Host app drives the transition (e.g. Angular Router withViewTransitions):
175
- // just reflect the new surface so the app's transition captures it.
176
- if (this.effectiveDisableViewTransition) {
177
- this.renderedStyle = newVal;
178
- return;
179
- }
180
-
181
- // Skip any in-progress transition immediately so rapid style changes never leave the nav stuck.
182
- vtTransitions.get(this)?.skipTransition();
183
- vtTransitions.delete(this);
184
-
185
- const doc = document as DocumentWithViewTransition;
186
- if (typeof doc.startViewTransition !== 'function') {
187
- this.renderedStyle = newVal;
188
- return;
189
- }
190
-
191
- ensureShellNavVtStyle();
192
- const origin = resolveShellNavRevealOrigin(
193
- this.el.querySelector('.panel-nav__footer-btn') as HTMLElement | null,
194
- );
195
- setShellNavRevealOriginVars(origin);
196
-
197
- const transition = doc.startViewTransition(() =>
198
- new Promise<void>(resolve => {
199
- vtResolvers.set(this, resolve);
200
- this.renderedStyle = newVal;
201
- })
202
- );
203
-
204
- vtTransitions.set(this, transition);
205
- transition.finished.finally(() => {
206
- if (vtTransitions.get(this) === transition) vtTransitions.delete(this);
207
- vtResolvers.delete(this);
208
- });
209
-
210
- transition.ready
211
- .then(() => animateShellNavRadialReveal(origin))
212
- .catch(() => { /* transition was skipped or aborted */ });
148
+ onNavStyleChange(newVal: NavChromeStyle) {
149
+ this.renderedStyle = newVal;
213
150
  }
214
151
 
215
152
  componentWillLoad() {
@@ -231,16 +168,6 @@ export class PanelNav {
231
168
  if (this.breakpoint > 0) this.connectResizeObserver();
232
169
  }
233
170
 
234
- componentDidRender() {
235
- // If a view transition callback is waiting for the render to complete,
236
- // resolve it now so the "after" snapshot is taken at exactly the right moment.
237
- const resolve = vtResolvers.get(this);
238
- if (resolve) {
239
- vtResolvers.delete(this);
240
- resolve();
241
- }
242
- }
243
-
244
171
  disconnectedCallback() {
245
172
  this.disconnectResizeObserver();
246
173
  this.clearEdgeOverlayTimer();
@@ -292,7 +219,9 @@ export class PanelNav {
292
219
 
293
220
  /** Re-parse props assigned by the host after componentWillLoad (Angular ngAfterViewInit). */
294
221
  private syncHostPropsIfNeeded() {
295
- this.syncRenderedStyleIfNeeded();
222
+ if (shouldResyncPanelNavStyle(this.renderedStyle, this.navStyle)) {
223
+ this.renderedStyle = this.navStyle;
224
+ }
296
225
 
297
226
  if (shouldResyncPanelNavGroups(this.parsedGroups, this.groups)) {
298
227
  this.onGroupsChange(this.groups);
@@ -301,19 +230,6 @@ export class PanelNav {
301
230
  }
302
231
  }
303
232
 
304
- /** Align `renderedStyle` with `style` when host bindings land after first paint. */
305
- private syncRenderedStyleIfNeeded() {
306
- if (!shouldResyncPanelNavStyle(this.renderedStyle, this.navStyle)) return;
307
-
308
- if (this.effectiveDisableViewTransition) {
309
- vtTransitions.get(this)?.skipTransition();
310
- vtTransitions.delete(this);
311
- this.renderedStyle = this.navStyle;
312
- } else {
313
- void this.onNavStyleChange(this.navStyle);
314
- }
315
- }
316
-
317
233
  /** Poll across animation frames — host props may land without triggering @Watch. */
318
234
  private scheduleDeferredHostPropSync() {
319
235
  let remaining = PanelNav.HOST_PROP_SYNC_BUDGET;
@@ -507,14 +423,16 @@ export class PanelNav {
507
423
  }
508
424
 
509
425
  render() {
510
- const isNavigation = this.renderedStyle === 'navigation';
426
+ const chromeStyle = this.renderedStyle;
427
+ const isDashboardChrome = chromeStyle === 'dashboard';
428
+ const isDashboard = this.navStyle === 'dashboard';
511
429
  const collapsed = this.collapsed || this.viewportNarrow;
512
430
  const { userName, userInitial } = this;
513
431
 
514
432
  const navCls: Record<string, boolean> = {
515
433
  'panel-nav': true,
516
- 'panel-nav--navigation': isNavigation,
517
- 'panel-nav--default': !isNavigation,
434
+ 'panel-nav--dashboard': isDashboard,
435
+ 'panel-nav--settings': !isDashboard,
518
436
  'panel-nav--collapsed': collapsed,
519
437
  'panel-nav--animating': this.isAnimating,
520
438
  'panel-nav--at-bottom': this.atBottom,
@@ -522,7 +440,10 @@ export class PanelNav {
522
440
 
523
441
  return (
524
442
  <Host style={{ display: 'block', position: 'relative' }}>
525
- <nav class={navCls} aria-label={isNavigation ? 'Main navigation' : 'Settings navigation'}>
443
+ <nav
444
+ class={navCls}
445
+ aria-label={isDashboardChrome ? 'Dashboard navigation' : 'Settings navigation'}
446
+ >
526
447
 
527
448
  {/* ── Header: Motive logo, reveals collapse toggle on hover ── */}
528
449
  <div class="panel-nav__header">
@@ -581,15 +502,14 @@ export class PanelNav {
581
502
 
582
503
  {/* ── Footer ── */}
583
504
  <div class="panel-nav__footer">
584
- {/* Left icon button — Gear in navigation style, Dashboard in default style */}
585
505
  <button
586
506
  type="button"
587
507
  class="panel-nav__footer-btn"
588
- title={isNavigation ? 'Settings' : 'Dashboard'}
589
- aria-label={isNavigation ? 'Open settings' : 'Go to dashboard'}
508
+ title={isDashboardChrome ? 'Settings' : 'Dashboard'}
509
+ aria-label={isDashboardChrome ? 'Open settings' : 'Go to dashboard'}
590
510
  onClick={() => this.handleFooterAction()}
591
511
  >
592
- <ds-icon name={isNavigation ? 'Gear' : 'Dashboard'} size="md" color="inherit" />
512
+ <ds-icon name={isDashboardChrome ? 'Gear' : 'Dashboard'} size="md" color="inherit" />
593
513
  </button>
594
514
 
595
515
  {/* Right user — label fades like nav items; right icon cross-fades chevron ↔ circle+initial */}
@@ -12,7 +12,6 @@ export {
12
12
  clearNavStyleHint,
13
13
  resolvePanelNavStyle,
14
14
  shouldResyncPanelNavStyle,
15
- ensurePanelNavVtStyle,
16
15
  deriveActiveIdFromUrl,
17
16
  parsePanelNavGroups,
18
17
  } from './panel-nav-utils';
@@ -7,7 +7,6 @@ import {
7
7
  setNavStyleHint,
8
8
  shouldResyncNavChromeStyle,
9
9
  } from '../../nav/nav-chrome';
10
- import { ensureShellNavVtStyle } from '../../nav/shell-view-transition';
11
10
 
12
11
  export type { NavChromeStyle } from '../../nav/nav-chrome';
13
12
  export {
@@ -19,18 +18,6 @@ export {
19
18
  shouldResyncNavChromeStyle as shouldResyncPanelNavStyle,
20
19
  };
21
20
 
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;
33
-
34
21
  /** Whether `path` matches `href` at a segment boundary (exact or child path). */
35
22
  export function hrefMatchesPath(path: string, href: string): boolean {
36
23
  return path === href || path.startsWith(`${href}/`);