@momentum-design/components 0.123.4 → 0.124.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 (31) hide show
  1. package/dist/browser/index.js +406 -295
  2. package/dist/browser/index.js.map +3 -3
  3. package/dist/components/dialog/dialog.styles.js +0 -2
  4. package/dist/components/menubar/menubar.component.js +1 -1
  5. package/dist/components/menuitem/menuitem.styles.js +1 -1
  6. package/dist/components/menusection/menusection.component.d.ts +5 -0
  7. package/dist/components/menusection/menusection.component.js +5 -0
  8. package/dist/components/menusection/menusection.styles.js +10 -7
  9. package/dist/components/navmenuitem/navmenuitem.component.d.ts +74 -27
  10. package/dist/components/navmenuitem/navmenuitem.component.js +135 -87
  11. package/dist/components/navmenuitem/navmenuitem.constants.d.ts +1 -0
  12. package/dist/components/navmenuitem/navmenuitem.constants.js +1 -0
  13. package/dist/components/navmenuitem/navmenuitem.styles.js +64 -29
  14. package/dist/components/popover/popover.component.js +4 -2
  15. package/dist/components/sidenavigation/sidenavigation.component.d.ts +50 -6
  16. package/dist/components/sidenavigation/sidenavigation.component.js +132 -25
  17. package/dist/components/sidenavigation/sidenavigation.constants.d.ts +1 -0
  18. package/dist/components/sidenavigation/sidenavigation.constants.js +1 -0
  19. package/dist/components/sidenavigation/sidenavigation.context.d.ts +1 -2
  20. package/dist/components/sidenavigation/sidenavigation.context.js +8 -9
  21. package/dist/components/sidenavigation/sidenavigation.styles.js +76 -8
  22. package/dist/custom-elements.json +2196 -1986
  23. package/dist/react/index.d.ts +3 -3
  24. package/dist/react/index.js +3 -3
  25. package/dist/react/menusection/index.d.ts +5 -0
  26. package/dist/react/menusection/index.js +5 -0
  27. package/dist/react/navmenuitem/index.d.ts +9 -3
  28. package/dist/react/navmenuitem/index.js +9 -3
  29. package/dist/react/sidenavigation/index.d.ts +12 -2
  30. package/dist/react/sidenavigation/index.js +12 -2
  31. package/package.json +1 -1
@@ -4,10 +4,15 @@ const styles = [
4
4
  hostFitContentStyles,
5
5
  css `
6
6
  :host {
7
+ --mdc-navmenuitem-in-sidenav-expanded-width: var(--mdc-sidenavigation-expanded-width, 100%);
8
+ --mdc-navmenuitem-in-sidenav-expanded-margin-left: var(--mdc-sidenavigation-expanded-left-padding, 1rem);
9
+ --mdc-navmenuitem-in-sidenav-expanded-margin-right: var(--mdc-sidenavigation-expanded-right-padding, 1rem);
10
+ --mdc-navmenuitem-in-sidenav-collapsed-width: var(--mdc-sidenavigation-collapsed-width, fit-content);
11
+ --mdc-navmenuitem-in-sidenav-collapsed-margin-left: var(--mdc-sidenavigation-collapsed-left-padding, 1rem);
12
+ --mdc-navmenuitem-in-sidenav-collapsed-margin-right: var(--mdc-sidenavigation-collapsed-right-padding, 1rem);
13
+
7
14
  --mdc-navmenuitem-color: var(--mds-color-theme-text-primary-normal);
8
15
  --mdc-navmenuitem-disabled-color: var(--mds-color-theme-text-primary-disabled);
9
- --mdc-navmenuitem-border-color: var(--mds-color-theme-outline-button-normal);
10
- --mdc-navmenuitem-expanded-width: 12.75rem;
11
16
 
12
17
  /* Background color when in default (normal) or active state */
13
18
  --mdc-navmenuitem-rest-active-background-color: var(--mds-color-theme-button-secondary-active-normal);
@@ -19,30 +24,62 @@ const styles = [
19
24
  --mdc-navmenuitem-disabled-active-background-color: var(--mds-color-theme-button-secondary-active-disabled);
20
25
 
21
26
  position: relative;
27
+ flex-shrink: 0;
22
28
  display: flex;
23
29
  align-items: center;
24
30
  gap: 0.5rem;
25
31
  padding: 0.5rem;
26
32
  color: var(--mdc-navmenuitem-color);
27
- border-color: var(--mdc-navmenuitem-border-color);
28
33
  border-radius: 0.5rem;
29
34
  cursor: pointer;
30
35
  }
31
36
 
37
+ :host::part(icon-container) {
38
+ position: relative;
39
+ }
40
+
41
+ :host([active]:not([cannot-activate]))::part(regular-icon) {
42
+ display: none;
43
+ }
44
+
45
+ :host([active]:not([cannot-activate]))::part(filled-icon) {
46
+ display: block;
47
+ }
48
+
49
+ :host::part(regular-icon) {
50
+ display: block;
51
+ }
52
+
53
+ :host::part(filled-icon) {
54
+ display: none;
55
+ }
56
+
57
+ :host([in-menupopover]) {
58
+ width: 100%;
59
+ }
60
+
32
61
  :host(:not([in-menupopover])) {
33
62
  border-radius: 1.25rem;
34
63
  }
35
64
 
36
- :host(:not([in-menupopover]):dir(ltr)) {
37
- margin-left: 1rem;
38
- }
65
+ :host([show-label]:not([in-menupopover])) {
66
+ width: calc(
67
+ var(--mdc-navmenuitem-in-sidenav-expanded-width) - var(--mdc-navmenuitem-in-sidenav-expanded-margin-left) - var(
68
+ --mdc-navmenuitem-in-sidenav-expanded-margin-right
69
+ )
70
+ );
39
71
 
40
- :host(:not([in-menupopover]):dir(rtl)) {
41
- margin-right: 1rem;
72
+ margin-inline-start: var(--mdc-navmenuitem-in-sidenav-expanded-margin-left);
42
73
  }
43
74
 
44
- :host([show-label]) {
45
- width: var(--mdc-navmenuitem-expanded-width);
75
+ :host(:not([show-label]):not([in-menupopover])) {
76
+ width: calc(
77
+ var(--mdc-navmenuitem-in-sidenav-collapsed-width) - var(--mdc-navmenuitem-in-sidenav-collapsed-margin-left) - var(
78
+ --mdc-navmenuitem-in-sidenav-collapsed-margin-right
79
+ )
80
+ );
81
+
82
+ margin-inline-start: var(--mdc-navmenuitem-in-sidenav-collapsed-margin-left);
46
83
  }
47
84
 
48
85
  :host([active]) {
@@ -86,13 +123,23 @@ const styles = [
86
123
  visibility: hidden;
87
124
  }
88
125
 
89
- :host(:dir(ltr))::before {
90
- left: -1rem;
126
+ :host([show-label]:dir(ltr))::before {
127
+ left: calc(-1 * var(--mdc-navmenuitem-in-sidenav-expanded-margin-left));
128
+ border-radius: 0 0.25rem 0.25rem 0;
129
+ }
130
+
131
+ :host([show-label]:dir(rtl))::before {
132
+ right: calc(-1 * var(--mdc-navmenuitem-in-sidenav-expanded-margin-left));
133
+ border-radius: 0.25rem 0 0 0.25rem;
134
+ }
135
+
136
+ :host(:not([show-label]):dir(ltr))::before {
137
+ left: calc(-1 * var(--mdc-navmenuitem-in-sidenav-collapsed-margin-left));
91
138
  border-radius: 0 0.25rem 0.25rem 0;
92
139
  }
93
140
 
94
- :host(:dir(rtl))::before {
95
- right: -1rem;
141
+ :host(:not([show-label]):dir(rtl))::before {
142
+ right: calc(-1 * var(--mdc-navmenuitem-in-sidenav-collapsed-margin-left));
96
143
  border-radius: 0.25rem 0 0 0.25rem;
97
144
  }
98
145
 
@@ -111,10 +158,6 @@ const styles = [
111
158
  white-space: nowrap;
112
159
  }
113
160
 
114
- :host::part(icon-container) {
115
- position: relative;
116
- }
117
-
118
161
  :host(:dir(ltr))::part(badge) {
119
162
  position: absolute;
120
163
  right: -0.375rem;
@@ -129,23 +172,15 @@ const styles = [
129
172
 
130
173
  :host(:not([show-label]))::part(trailing-arrow) {
131
174
  --mdc-icon-size: 0.75rem;
132
- }
133
-
134
- :host([show-label])::part(trailing-arrow) {
135
- --mdc-icon-size: 1rem;
136
175
  flex-shrink: 0;
137
- }
138
176
 
139
- :host(:dir(ltr))::part(arrow) {
140
177
  position: absolute;
141
- right: -0.75rem;
178
+ inset-inline-end: -0.25rem;
142
179
  top: 0.875rem;
143
180
  }
144
181
 
145
- :host(:dir(rtl))::part(arrow) {
146
- position: absolute;
147
- left: -0.75rem;
148
- top: 0.875rem;
182
+ :host([show-label])::part(trailing-arrow) {
183
+ flex-shrink: 0;
149
184
  }
150
185
 
151
186
  :host mdc-badge {
@@ -519,10 +519,12 @@ class Popover extends BackdropMixin(PreventScrollMixin(FocusTrapMixin(Component)
519
519
  * This method checks if the trigger element has visible focus or is being hovered.
520
520
  */
521
521
  this.handleFocusIn = (event) => {
522
- var _a;
522
+ var _a, _b, _c, _d;
523
523
  if (!this.isEventFromTrigger(event))
524
524
  return;
525
- if (((_a = this.triggerElement) === null || _a === void 0 ? void 0 : _a.matches(':focus-visible')) || this.isHovered) {
525
+ if (((_a = this.triggerElement) === null || _a === void 0 ? void 0 : _a.matches(':focus-visible')) ||
526
+ ((_d = (_c = (_b = this.triggerElement) === null || _b === void 0 ? void 0 : _b.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('.mdc-focus-ring')) === null || _d === void 0 ? void 0 : _d.matches(':focus-visible')) ||
527
+ this.isHovered) {
526
528
  this.show();
527
529
  }
528
530
  };
@@ -7,7 +7,7 @@ import SideNavigationContext from './sidenavigation.context';
7
7
  * typically used in layouts with persistent or collapsible sidebars.
8
8
  *
9
9
  * ## Features:
10
- * - Supports four layout variants: `fixed-collapsed`, `fixed-expanded`, `flexible`, and `hidden`
10
+ * - Supports five layout variants: `fixed-collapsed`, `fixed-expanded`, `flexible`, `flexible-on-hover`, and `hidden`
11
11
  * - Toggleable expand/collapse behavior
12
12
  * - Displays brand logo and customer name
13
13
  * - Serves as a context provider for descendant components - `mdc-menubar` and `mdc-navmenuitem`
@@ -47,13 +47,17 @@ import SideNavigationContext from './sidenavigation.context';
47
47
  * @tagname mdc-sidenavigation
48
48
  *
49
49
  * @slot scrollable-section - Slot for the scrollable content area of the side navigation.
50
+ * @slot scrollable-menubar - Slot for the menubar inside the scrollable section.
50
51
  * @slot fixed-section - Slot for the fixed content area of the side navigation.
52
+ * @slot fixed-menubar - Slot for the menubar inside the fixed section.
51
53
  * @slot brand-logo - Slot for the brand logo (e.g., icon or img).
52
54
  *
53
55
  * @csspart side-navigation-container - The main container wrapping the entire side navigation.
54
56
  * @csspart scrollable-section - The scrollable section of the side navigation.
55
- * @csspart fixed-section - The fixed section of the side navigation.
57
+ * @csspart scrollable-menubar - The menubar inside the scrollable section.
56
58
  * @csspart separator - The divider between the scrollable and fixed sections.
59
+ * @csspart fixed-section - The fixed section of the side navigation.
60
+ * @csspart fixed-menubar - The menubar inside the fixed section.
57
61
  * @csspart brand-logo-container - The container wrapping the brand logo and footer text.
58
62
  * @csspart footer-text - The footer text label in the fixed section.
59
63
  * @csspart vertical-divider - The vertical divider between the scrollable and fixed sections.
@@ -63,28 +67,40 @@ import SideNavigationContext from './sidenavigation.context';
63
67
  * @event activechange - (React: onActiveChange) Dispatched when the active state of a nested navmenuitem changes.
64
68
  *
65
69
  * @cssproperty --mdc-sidenavigation-expanded-width - width of the sideNavigation when expanded
70
+ * @cssproperty --mdc-sidenavigation-expanded-left-padding - padding for the left side of navmenuitems, when expanded
71
+ * @cssproperty --mdc-sidenavigation-expanded-right-padding - padding for the right side of navmenuitems, when expanded
66
72
  * @cssproperty --mdc-sidenavigation-collapsed-width - width of the sideNavigation when collapsed
73
+ * @cssproperty --mdc-sidenavigation-collapsed-left-padding - padding for the left side of navmenuitems, when collapsed
74
+ * @cssproperty --mdc-sidenavigation-collapsed-right-padding - padding for the right side of navmenuitems, when collapsed
75
+ * @cssproperty --mdc-sidenavigation-top-padding - padding for the top of the scrollable section - note: if setting to 0 focus ring might be cut off
76
+ * @cssproperty --mdc-sidenavigation-bottom-padding - padding for the bottom of the scrollable section
67
77
  * @cssproperty --mdc-sidenavigation-vertical-divider-button-z-index - z-index of the vertical divider button
68
78
  */
69
79
  declare class SideNavigation extends Provider<SideNavigationContext> {
70
80
  /**
71
- * Four variants of the sideNavigation
81
+ * Five variants of the sideNavigation
72
82
  * - **fixed-collapsed**: Shows icons without labels and has fixed width, 4.5rem.
73
83
  * - **fixed-expanded**: Shows icons with labels and has fixed width, 15rem.
74
84
  * - **flexible**: Toggles between collapsed/expanded states.
85
+ * - **flexible-on-hover**: Similar to flexible, but the grabber button is only visible on hover or focus.
75
86
  * - **hidden**: Removes the sidenavigation from the DOM.
76
87
  * @default flexible
77
88
  */
78
89
  variant: SideNavigationVariant;
79
90
  /**
80
91
  * Displays footer text in the bottom section of the sidenavigation.
92
+ *
93
+ * Note: if footerText is not provided, the bottom brand logo section will not be rendered.
81
94
  * @default ''
82
95
  */
83
96
  footerText: string;
84
97
  /**
85
98
  * Determines whether the sideNavigation is expanded or not.
86
99
  *
87
- * @internal
100
+ * NOTE: For `fixed-collapsed` and `fixed-expanded` variants, this property is hard set to `false` and `true` respectively.
101
+ * For `flexible` and `flexible-on-hover` variants, this property can be toggled / controlled from parent.
102
+ *
103
+ * @default true
88
104
  */
89
105
  expanded?: boolean;
90
106
  /**
@@ -95,11 +111,39 @@ declare class SideNavigation extends Provider<SideNavigationContext> {
95
111
  */
96
112
  grabberBtnAriaLabel?: string;
97
113
  /**
98
- * Tooltip text shown on parent nav items when a child is active.
114
+ * Hides the divider between the scrollable and fixed sections when set to true.
115
+ * @default false
99
116
  */
100
- parentNavTooltipText?: string;
117
+ hideFixedSectionDivider: boolean;
101
118
  constructor();
102
119
  connectedCallback(): void;
120
+ disconnectedCallback(): void;
121
+ private isHovered;
122
+ private isFocused;
123
+ /** @internal */
124
+ private handleMouseEnter;
125
+ /** @internal */
126
+ private handleMouseLeave;
127
+ /** @internal */
128
+ private handleFocusIn;
129
+ /** @internal */
130
+ private handleFocusOut;
131
+ /** @internal */
132
+ private showGrabberButton;
133
+ /** @internal */
134
+ private hideGrabberButton;
135
+ /**
136
+ * Sets up event listeners for flexible-on-hover variant.
137
+ * Only adds listeners if the variant is flexible-on-hover.
138
+ * @internal
139
+ */
140
+ private setupFlexibleOnHoverListeners;
141
+ /**
142
+ * Removes event listeners for flexible-on-hover variant.
143
+ * Safe to call regardless of current variant.
144
+ * @internal
145
+ */
146
+ private removeFlexibleOnHoverListeners;
103
147
  static get Context(): {
104
148
  __context__: SideNavigationContext;
105
149
  };
@@ -23,7 +23,7 @@ import styles from './sidenavigation.styles';
23
23
  * typically used in layouts with persistent or collapsible sidebars.
24
24
  *
25
25
  * ## Features:
26
- * - Supports four layout variants: `fixed-collapsed`, `fixed-expanded`, `flexible`, and `hidden`
26
+ * - Supports five layout variants: `fixed-collapsed`, `fixed-expanded`, `flexible`, `flexible-on-hover`, and `hidden`
27
27
  * - Toggleable expand/collapse behavior
28
28
  * - Displays brand logo and customer name
29
29
  * - Serves as a context provider for descendant components - `mdc-menubar` and `mdc-navmenuitem`
@@ -63,13 +63,17 @@ import styles from './sidenavigation.styles';
63
63
  * @tagname mdc-sidenavigation
64
64
  *
65
65
  * @slot scrollable-section - Slot for the scrollable content area of the side navigation.
66
+ * @slot scrollable-menubar - Slot for the menubar inside the scrollable section.
66
67
  * @slot fixed-section - Slot for the fixed content area of the side navigation.
68
+ * @slot fixed-menubar - Slot for the menubar inside the fixed section.
67
69
  * @slot brand-logo - Slot for the brand logo (e.g., icon or img).
68
70
  *
69
71
  * @csspart side-navigation-container - The main container wrapping the entire side navigation.
70
72
  * @csspart scrollable-section - The scrollable section of the side navigation.
71
- * @csspart fixed-section - The fixed section of the side navigation.
73
+ * @csspart scrollable-menubar - The menubar inside the scrollable section.
72
74
  * @csspart separator - The divider between the scrollable and fixed sections.
75
+ * @csspart fixed-section - The fixed section of the side navigation.
76
+ * @csspart fixed-menubar - The menubar inside the fixed section.
73
77
  * @csspart brand-logo-container - The container wrapping the brand logo and footer text.
74
78
  * @csspart footer-text - The footer text label in the fixed section.
75
79
  * @csspart vertical-divider - The vertical divider between the scrollable and fixed sections.
@@ -79,7 +83,13 @@ import styles from './sidenavigation.styles';
79
83
  * @event activechange - (React: onActiveChange) Dispatched when the active state of a nested navmenuitem changes.
80
84
  *
81
85
  * @cssproperty --mdc-sidenavigation-expanded-width - width of the sideNavigation when expanded
86
+ * @cssproperty --mdc-sidenavigation-expanded-left-padding - padding for the left side of navmenuitems, when expanded
87
+ * @cssproperty --mdc-sidenavigation-expanded-right-padding - padding for the right side of navmenuitems, when expanded
82
88
  * @cssproperty --mdc-sidenavigation-collapsed-width - width of the sideNavigation when collapsed
89
+ * @cssproperty --mdc-sidenavigation-collapsed-left-padding - padding for the left side of navmenuitems, when collapsed
90
+ * @cssproperty --mdc-sidenavigation-collapsed-right-padding - padding for the right side of navmenuitems, when collapsed
91
+ * @cssproperty --mdc-sidenavigation-top-padding - padding for the top of the scrollable section - note: if setting to 0 focus ring might be cut off
92
+ * @cssproperty --mdc-sidenavigation-bottom-padding - padding for the bottom of the scrollable section
83
93
  * @cssproperty --mdc-sidenavigation-vertical-divider-button-z-index - z-index of the vertical divider button
84
94
  */
85
95
  class SideNavigation extends Provider {
@@ -89,19 +99,88 @@ class SideNavigation extends Provider {
89
99
  initialValue: new SideNavigationContext(DEFAULTS.VARIANT, true),
90
100
  });
91
101
  /**
92
- * Four variants of the sideNavigation
102
+ * Five variants of the sideNavigation
93
103
  * - **fixed-collapsed**: Shows icons without labels and has fixed width, 4.5rem.
94
104
  * - **fixed-expanded**: Shows icons with labels and has fixed width, 15rem.
95
105
  * - **flexible**: Toggles between collapsed/expanded states.
106
+ * - **flexible-on-hover**: Similar to flexible, but the grabber button is only visible on hover or focus.
96
107
  * - **hidden**: Removes the sidenavigation from the DOM.
97
108
  * @default flexible
98
109
  */
99
110
  this.variant = DEFAULTS.VARIANT;
100
111
  /**
101
112
  * Displays footer text in the bottom section of the sidenavigation.
113
+ *
114
+ * Note: if footerText is not provided, the bottom brand logo section will not be rendered.
102
115
  * @default ''
103
116
  */
104
117
  this.footerText = '';
118
+ /**
119
+ * Hides the divider between the scrollable and fixed sections when set to true.
120
+ * @default false
121
+ */
122
+ this.hideFixedSectionDivider = false;
123
+ this.isHovered = false;
124
+ this.isFocused = false;
125
+ /** @internal */
126
+ this.handleMouseEnter = () => {
127
+ this.isHovered = true;
128
+ this.showGrabberButton();
129
+ };
130
+ /** @internal */
131
+ this.handleMouseLeave = () => {
132
+ this.isHovered = false;
133
+ if (!this.isFocused) {
134
+ this.hideGrabberButton();
135
+ }
136
+ };
137
+ /** @internal */
138
+ this.handleFocusIn = (e) => {
139
+ if (!this.isFocused) {
140
+ if (this.navMenuItems.find(item => item === e.target)) {
141
+ // if target of focusin event is navMenuItem and it has not a visible focus, do not proceed further.
142
+ // this is to avoid showing grabber button on click events
143
+ if (!e.target.matches(':focus-visible')) {
144
+ return;
145
+ }
146
+ }
147
+ this.isFocused = true;
148
+ this.showGrabberButton();
149
+ }
150
+ };
151
+ /** @internal */
152
+ this.handleFocusOut = (e) => {
153
+ if (!this.contains(e.relatedTarget)) {
154
+ this.isFocused = false;
155
+ if (!this.isHovered) {
156
+ this.hideGrabberButton();
157
+ }
158
+ }
159
+ };
160
+ /**
161
+ * Sets up event listeners for flexible-on-hover variant.
162
+ * Only adds listeners if the variant is flexible-on-hover.
163
+ * @internal
164
+ */
165
+ this.setupFlexibleOnHoverListeners = () => {
166
+ if (this.variant === VARIANTS.FLEXIBLE_ON_HOVER) {
167
+ this.addEventListener('mouseenter', this.handleMouseEnter);
168
+ this.addEventListener('mouseleave', this.handleMouseLeave);
169
+ this.addEventListener('focusin', this.handleFocusIn);
170
+ this.addEventListener('focusout', this.handleFocusOut);
171
+ }
172
+ };
173
+ /**
174
+ * Removes event listeners for flexible-on-hover variant.
175
+ * Safe to call regardless of current variant.
176
+ * @internal
177
+ */
178
+ this.removeFlexibleOnHoverListeners = () => {
179
+ this.removeEventListener('mouseenter', this.handleMouseEnter);
180
+ this.removeEventListener('mouseleave', this.handleMouseLeave);
181
+ this.removeEventListener('focusin', this.handleFocusIn);
182
+ this.removeEventListener('focusout', this.handleFocusOut);
183
+ };
105
184
  /**
106
185
  * Handle the navMenuItem active change event fired from the nested navMenuItem.
107
186
  * @internal
@@ -126,6 +205,19 @@ class SideNavigation extends Provider {
126
205
  connectedCallback() {
127
206
  super.connectedCallback();
128
207
  this.role = ROLE.NAVIGATION;
208
+ this.setupFlexibleOnHoverListeners();
209
+ }
210
+ disconnectedCallback() {
211
+ super.disconnectedCallback();
212
+ this.removeFlexibleOnHoverListeners();
213
+ }
214
+ /** @internal */
215
+ showGrabberButton() {
216
+ this.toggleAttribute('data-grabber-visible', true);
217
+ }
218
+ /** @internal */
219
+ hideGrabberButton() {
220
+ this.toggleAttribute('data-grabber-visible', false);
129
221
  }
130
222
  static get Context() {
131
223
  return SideNavigationContext.context;
@@ -134,6 +226,9 @@ class SideNavigation extends Provider {
134
226
  super.updated(changedProperties);
135
227
  if (changedProperties.has('variant')) {
136
228
  this.setVariant(this.variant);
229
+ // Re-setup listeners when variant changes
230
+ this.removeFlexibleOnHoverListeners();
231
+ this.setupFlexibleOnHoverListeners();
137
232
  // hard set expanded state for fixed variants:
138
233
  switch (this.variant) {
139
234
  case VARIANTS.FIXED_EXPANDED:
@@ -151,8 +246,8 @@ class SideNavigation extends Provider {
151
246
  }
152
247
  firstUpdated(changedProperties) {
153
248
  super.firstUpdated(changedProperties);
154
- if (this.variant === VARIANTS.FLEXIBLE && this.expanded === undefined) {
155
- // if on first update the variant is flexible and expanded is not set, default to expanded true
249
+ if ((this.variant === VARIANTS.FLEXIBLE || this.variant === VARIANTS.FLEXIBLE_ON_HOVER) &&
250
+ this.expanded === undefined) {
156
251
  this.expanded = true;
157
252
  this.updateContext();
158
253
  }
@@ -164,12 +259,9 @@ class SideNavigation extends Provider {
164
259
  * Is called on every re-render, see Provider class
165
260
  */
166
261
  updateContext() {
167
- if (this.context.value.variant !== this.variant ||
168
- this.context.value.expanded !== this.expanded ||
169
- this.context.value.parentNavTooltipText !== this.parentNavTooltipText) {
262
+ if (this.context.value.variant !== this.variant || this.context.value.expanded !== this.expanded) {
170
263
  this.context.value.variant = this.variant;
171
264
  this.context.value.expanded = this.expanded;
172
- this.context.value.parentNavTooltipText = this.parentNavTooltipText;
173
265
  this.context.updateObservers();
174
266
  }
175
267
  }
@@ -197,8 +289,14 @@ class SideNavigation extends Provider {
197
289
  *
198
290
  * @internal
199
291
  */
200
- toggleSideNavigation() {
292
+ toggleSideNavigation(e) {
201
293
  this.expanded = !this.expanded;
294
+ if (this.expanded === false && this.variant === VARIANTS.FLEXIBLE_ON_HOVER && e.pointerType === 'mouse') {
295
+ // If collapsing via mouse click when in flexible-on-hover mode, reset hover/focus states
296
+ this.isHovered = false;
297
+ this.isFocused = false;
298
+ this.hideGrabberButton();
299
+ }
202
300
  this.dispatchEvent(new CustomEvent('toggle', { detail: { expanded: this.expanded } }));
203
301
  }
204
302
  preventScrollOnSpace(event) {
@@ -216,29 +314,38 @@ class SideNavigation extends Provider {
216
314
  <div part="side-navigation-container" id="side-nav-container">
217
315
  <div part="scrollable-section" tabindex="-1" @keydown=${this.preventScrollOnSpace}>
218
316
  <slot name="scrollable-section">
219
- <mdc-menubar>
317
+ <mdc-menubar part="scrollable-menubar">
220
318
  <slot name="scrollable-menubar"></slot>
221
319
  </mdc-menubar>
222
320
  </slot>
223
321
  </div>
224
- <mdc-divider variant="gradient" part="separator"></mdc-divider>
322
+ ${!this.hideFixedSectionDivider
323
+ ? html `<mdc-divider variant="gradient" part="separator"></mdc-divider>`
324
+ : nothing}
225
325
  <div part="fixed-section">
226
326
  <slot name="fixed-section">
227
- <mdc-menubar>
327
+ <mdc-menubar part="fixed-menubar">
228
328
  <slot name="fixed-menubar"></slot>
229
329
  </mdc-menubar>
230
330
  </slot>
231
- <div part="brand-logo-container">
232
- <slot name="brand-logo"></slot>
233
- ${this.expanded
234
- ? html `<mdc-text type=${TYPE.BODY_MIDSIZE_MEDIUM} tagname=${VALID_TEXT_TAGS.SPAN} part="footer-text"
235
- >${this.footerText}</mdc-text
236
- >`
331
+ ${this.footerText
332
+ ? html `
333
+ <div part="brand-logo-container">
334
+ <slot name="brand-logo"></slot>
335
+ ${this.expanded
336
+ ? html ` <mdc-text
337
+ type=${TYPE.BODY_MIDSIZE_MEDIUM}
338
+ tagname=${VALID_TEXT_TAGS.SPAN}
339
+ part="footer-text"
340
+ >${this.footerText}</mdc-text
341
+ >`
342
+ : nothing}
343
+ </div>
344
+ `
237
345
  : nothing}
238
- </div>
239
346
  </div>
240
347
  </div>
241
- ${this.variant === VARIANTS.FLEXIBLE
348
+ ${this.variant === VARIANTS.FLEXIBLE || this.variant === VARIANTS.FLEXIBLE_ON_HOVER
242
349
  ? html `<mdc-divider
243
350
  part="vertical-divider"
244
351
  orientation=${DIVIDER_ORIENTATION.VERTICAL}
@@ -268,7 +375,7 @@ __decorate([
268
375
  __metadata("design:type", String)
269
376
  ], SideNavigation.prototype, "footerText", void 0);
270
377
  __decorate([
271
- property({ type: Boolean, reflect: true }),
378
+ property({ type: Boolean, reflect: true, attribute: 'expanded' }),
272
379
  __metadata("design:type", Boolean)
273
380
  ], SideNavigation.prototype, "expanded", void 0);
274
381
  __decorate([
@@ -276,7 +383,7 @@ __decorate([
276
383
  __metadata("design:type", String)
277
384
  ], SideNavigation.prototype, "grabberBtnAriaLabel", void 0);
278
385
  __decorate([
279
- property({ type: String, reflect: true, attribute: 'parent-nav-tooltip-text' }),
280
- __metadata("design:type", String)
281
- ], SideNavigation.prototype, "parentNavTooltipText", void 0);
386
+ property({ type: Boolean, reflect: true, attribute: 'hide-fixed-section-divider' }),
387
+ __metadata("design:type", Boolean)
388
+ ], SideNavigation.prototype, "hideFixedSectionDivider", void 0);
282
389
  export default SideNavigation;
@@ -3,6 +3,7 @@ declare const VARIANTS: {
3
3
  FIXED_EXPANDED: string;
4
4
  FIXED_COLLAPSED: string;
5
5
  FLEXIBLE: string;
6
+ FLEXIBLE_ON_HOVER: string;
6
7
  HIDDEN: string;
7
8
  };
8
9
  declare const DEFAULTS: {
@@ -4,6 +4,7 @@ const VARIANTS = {
4
4
  FIXED_EXPANDED: 'fixed-expanded',
5
5
  FIXED_COLLAPSED: 'fixed-collapsed',
6
6
  FLEXIBLE: 'flexible',
7
+ FLEXIBLE_ON_HOVER: 'flexible-on-hover',
7
8
  HIDDEN: 'hidden',
8
9
  };
9
10
  const DEFAULTS = {
@@ -3,11 +3,10 @@ declare class SideNavigationContext {
3
3
  variant?: string;
4
4
  expanded?: boolean;
5
5
  private currentActiveNavMenuItem?;
6
- parentNavTooltipText?: string;
7
6
  static context: {
8
7
  __context__: SideNavigationContext;
9
8
  };
10
- constructor(defaultVariant?: string, defaultExpanded?: boolean, defaultParentNavTooltipText?: string);
9
+ constructor(defaultVariant?: string, defaultExpanded?: boolean);
11
10
  hasSiblingWithTriggerId(navMenuItem: NavMenuItem | undefined): boolean;
12
11
  private getParentNavMenuItems;
13
12
  setCurrentActiveNavMenuItem(navMenuItem: NavMenuItem | undefined): void;
@@ -1,13 +1,12 @@
1
+ /* eslint-disable no-param-reassign */
1
2
  import { createContext } from '@lit/context';
2
3
  import { TAG_NAME as MENUPOPOVER_TAGNAME } from '../menupopover/menupopover.constants';
3
4
  import { TAG_NAME as NAVMENUITEM_TAGNAME } from '../navmenuitem/navmenuitem.constants';
4
- import { POPOVER_PLACEMENT } from '../popover/popover.constants';
5
5
  import { TAG_NAME } from './sidenavigation.constants';
6
6
  class SideNavigationContext {
7
- constructor(defaultVariant, defaultExpanded, defaultParentNavTooltipText) {
7
+ constructor(defaultVariant, defaultExpanded) {
8
8
  this.variant = defaultVariant;
9
9
  this.expanded = defaultExpanded;
10
- this.parentNavTooltipText = defaultParentNavTooltipText;
11
10
  }
12
11
  hasSiblingWithTriggerId(navMenuItem) {
13
12
  var _a, _b;
@@ -47,7 +46,7 @@ class SideNavigationContext {
47
46
  setCurrentActiveNavMenuItem(navMenuItem) {
48
47
  var _a;
49
48
  const isSameItem = ((_a = this.currentActiveNavMenuItem) === null || _a === void 0 ? void 0 : _a.navId) === (navMenuItem === null || navMenuItem === void 0 ? void 0 : navMenuItem.navId);
50
- const shouldSkip = (navMenuItem === null || navMenuItem === void 0 ? void 0 : navMenuItem.disableAriaCurrent) || this.hasSiblingWithTriggerId(navMenuItem) || (navMenuItem === null || navMenuItem === void 0 ? void 0 : navMenuItem.softDisabled);
49
+ const shouldSkip = (navMenuItem === null || navMenuItem === void 0 ? void 0 : navMenuItem.cannotActivate) || this.hasSiblingWithTriggerId(navMenuItem) || (navMenuItem === null || navMenuItem === void 0 ? void 0 : navMenuItem.softDisabled);
51
50
  if (isSameItem || shouldSkip)
52
51
  return;
53
52
  // Clean up previous active item
@@ -56,8 +55,7 @@ class SideNavigationContext {
56
55
  this.currentActiveNavMenuItem.removeAttribute('active');
57
56
  const previousParents = this.getParentNavMenuItems(this.currentActiveNavMenuItem);
58
57
  previousParents.forEach(parent => {
59
- parent.removeAttribute('tooltip-text');
60
- parent.removeAttribute('tooltip-placement');
58
+ parent.hasActiveChild = false;
61
59
  parent.removeAttribute('active');
62
60
  });
63
61
  }
@@ -65,12 +63,13 @@ class SideNavigationContext {
65
63
  if (!navMenuItem)
66
64
  return;
67
65
  this.currentActiveNavMenuItem = navMenuItem;
68
- navMenuItem.setAttribute('aria-current', 'page');
66
+ if (!(navMenuItem === null || navMenuItem === void 0 ? void 0 : navMenuItem.disableAriaCurrent)) {
67
+ navMenuItem.setAttribute('aria-current', 'page');
68
+ }
69
69
  navMenuItem.setAttribute('active', '');
70
70
  const newParents = this.getParentNavMenuItems(navMenuItem);
71
71
  newParents.forEach(parent => {
72
- parent.setAttribute('tooltip-text', this.parentNavTooltipText || '');
73
- parent.setAttribute('tooltip-placement', POPOVER_PLACEMENT.BOTTOM);
72
+ parent.hasActiveChild = true;
74
73
  parent.setAttribute('active', '');
75
74
  });
76
75
  }