@redvars/peacock 3.5.0 → 3.5.1

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 (148) hide show
  1. package/dist/BaseButton-DuASuVth.js +219 -0
  2. package/dist/BaseButton-DuASuVth.js.map +1 -0
  3. package/dist/BaseHyperlinkMixin-BNuwbiEf.js +65 -0
  4. package/dist/BaseHyperlinkMixin-BNuwbiEf.js.map +1 -0
  5. package/dist/assets/components.css +1 -1
  6. package/dist/assets/components.css.map +1 -1
  7. package/dist/assets/styles.css +1 -1
  8. package/dist/assets/styles.css.map +1 -1
  9. package/dist/banner.js +12 -27
  10. package/dist/banner.js.map +1 -1
  11. package/dist/{button-DMN1dPAg.js → button-DouvOfEU.js} +77 -251
  12. package/dist/button-DouvOfEU.js.map +1 -0
  13. package/dist/{button-group-CX9CUUXk.js → button-group-CEdMwvJJ.js} +71 -42
  14. package/dist/button-group-CEdMwvJJ.js.map +1 -0
  15. package/dist/button-group.js +5 -5
  16. package/dist/button.js +3 -3
  17. package/dist/card.js +18 -73
  18. package/dist/card.js.map +1 -1
  19. package/dist/chart-bar.js.map +1 -1
  20. package/dist/chart-doughnut.js +2 -2
  21. package/dist/chart-doughnut.js.map +1 -1
  22. package/dist/chart-pie.js +2 -2
  23. package/dist/chart-pie.js.map +1 -1
  24. package/dist/chart-stacked-bar.js.map +1 -1
  25. package/dist/code-highlighter.js +2 -1
  26. package/dist/code-highlighter.js.map +1 -1
  27. package/dist/custom-elements-jsdocs.json +3105 -1494
  28. package/dist/custom-elements.json +9244 -7829
  29. package/dist/fab.js +421 -9
  30. package/dist/fab.js.map +1 -1
  31. package/dist/index.js +6 -6
  32. package/dist/{select-4pl4XBj7.js → navigation-rail-Lxetd5-Z.js} +2214 -1090
  33. package/dist/navigation-rail-Lxetd5-Z.js.map +1 -0
  34. package/dist/notification.js +3 -2
  35. package/dist/notification.js.map +1 -1
  36. package/dist/peacock-loader.js +22 -10
  37. package/dist/peacock-loader.js.map +1 -1
  38. package/dist/search.js +4 -0
  39. package/dist/search.js.map +1 -1
  40. package/dist/src/__mixins/BaseButtonMixin.d.ts +20 -0
  41. package/dist/src/__mixins/BaseHyperlinkMixin.d.ts +18 -0
  42. package/dist/src/__mixins/MixinConstructor.d.ts +1 -0
  43. package/dist/src/banner/banner.d.ts +0 -4
  44. package/dist/src/button/BaseButton.d.ts +4 -47
  45. package/dist/src/button/button/button.d.ts +32 -3
  46. package/dist/src/button/button-group/button-group.d.ts +2 -2
  47. package/dist/src/button/icon-button/icon-button.d.ts +33 -8
  48. package/dist/src/card/card.d.ts +4 -15
  49. package/dist/src/fab/fab.d.ts +4 -35
  50. package/dist/src/focus-ring/focus-ring.d.ts +11 -5
  51. package/dist/src/index.d.ts +3 -1
  52. package/dist/src/link/link.d.ts +1 -1
  53. package/dist/src/navigation-rail/index.d.ts +2 -0
  54. package/dist/src/navigation-rail/navigation-rail-item.d.ts +55 -0
  55. package/dist/src/navigation-rail/navigation-rail.d.ts +71 -0
  56. package/dist/src/sidebar-menu/index.d.ts +3 -0
  57. package/dist/src/sidebar-menu/sidebar-menu-item.d.ts +58 -0
  58. package/dist/src/sidebar-menu/sidebar-menu.d.ts +38 -0
  59. package/dist/src/sidebar-menu/sidebar-sub-menu.d.ts +35 -0
  60. package/dist/src/toolbar/toolbar.d.ts +10 -10
  61. package/dist/src/tooltip/tooltip.d.ts +3 -0
  62. package/dist/src/url-field/index.d.ts +1 -0
  63. package/dist/src/url-field/url-field.d.ts +48 -0
  64. package/dist/test/sidebar-menu.test.d.ts +1 -0
  65. package/dist/toolbar.js +10 -10
  66. package/dist/toolbar.js.map +1 -1
  67. package/dist/tsconfig.tsbuildinfo +1 -1
  68. package/package.json +1 -1
  69. package/readme.md +73 -65
  70. package/scss/mixin.scss +16 -0
  71. package/src/__mixins/BaseButtonMixin.ts +83 -0
  72. package/src/__mixins/BaseHyperlinkMixin.ts +68 -0
  73. package/src/__mixins/MixinConstructor.ts +1 -0
  74. package/src/{__base_element → __mixins}/README.md +2 -2
  75. package/src/banner/banner.scss +18 -22
  76. package/src/banner/banner.ts +1 -7
  77. package/src/button/BaseButton.ts +11 -100
  78. package/src/button/button/button-sizes.scss +4 -2
  79. package/src/button/button/button.ts +76 -23
  80. package/src/button/button-group/button-group.ts +2 -2
  81. package/src/button/icon-button/icon-button.ts +75 -33
  82. package/src/card/card.ts +11 -71
  83. package/src/chart-bar/chart-bar.ts +9 -14
  84. package/src/chart-bar/chart-stacked-bar.ts +12 -18
  85. package/src/chart-doughnut/chart-doughnut.ts +23 -27
  86. package/src/chart-pie/chart-pie.ts +19 -23
  87. package/src/checkbox/checkbox.scss +17 -34
  88. package/src/checkbox/checkbox.ts +3 -1
  89. package/src/code-highlighter/code-highlighter.scss +1 -0
  90. package/src/code-highlighter/code-highlighter.ts +1 -1
  91. package/src/date-picker/date-picker.ts +1 -1
  92. package/src/elevation/elevation.scss +5 -5
  93. package/src/fab/fab.ts +29 -100
  94. package/src/focus-ring/focus-ring.ts +47 -40
  95. package/src/index.ts +3 -1
  96. package/src/input/input.ts +3 -1
  97. package/src/link/link.ts +2 -2
  98. package/src/menu/menu-item/menu-item.ts +3 -1
  99. package/src/navigation-rail/index.ts +2 -0
  100. package/src/navigation-rail/navigation-rail-item.scss +216 -0
  101. package/src/navigation-rail/navigation-rail-item.ts +223 -0
  102. package/src/navigation-rail/navigation-rail.scss +72 -0
  103. package/src/navigation-rail/navigation-rail.ts +149 -0
  104. package/src/notification/notification.ts +3 -2
  105. package/src/number-field/number-field.ts +6 -4
  106. package/src/pagination/pagination.ts +6 -4
  107. package/src/peacock-loader.ts +22 -5
  108. package/src/search/search.ts +4 -0
  109. package/src/sidebar-menu/demo/index.html +68 -0
  110. package/src/sidebar-menu/index.ts +3 -0
  111. package/src/sidebar-menu/sidebar-menu-item.scss +102 -0
  112. package/src/sidebar-menu/sidebar-menu-item.ts +151 -0
  113. package/src/{tree-view/tree-view.scss → sidebar-menu/sidebar-menu.scss} +1 -1
  114. package/src/sidebar-menu/sidebar-menu.ts +182 -0
  115. package/src/sidebar-menu/sidebar-sub-menu.scss +130 -0
  116. package/src/sidebar-menu/sidebar-sub-menu.ts +160 -0
  117. package/src/skeleton/skeleton.scss +18 -24
  118. package/src/snackbar/snackbar.ts +1 -1
  119. package/src/tabs/tab.ts +4 -3
  120. package/src/text/text.css-component.scss +7 -1
  121. package/src/time-picker/time-picker.ts +1 -1
  122. package/src/toolbar/toolbar.ts +10 -10
  123. package/src/tooltip/tooltip.ts +24 -0
  124. package/src/url-field/index.ts +1 -0
  125. package/src/url-field/url-field.scss +50 -0
  126. package/src/url-field/url-field.ts +239 -0
  127. package/dist/button-DMN1dPAg.js.map +0 -1
  128. package/dist/button-group-CX9CUUXk.js.map +0 -1
  129. package/dist/fab-C5Nzxk0E.js +0 -497
  130. package/dist/fab-C5Nzxk0E.js.map +0 -1
  131. package/dist/select-4pl4XBj7.js.map +0 -1
  132. package/dist/spread-B5cgadZl.js +0 -32
  133. package/dist/spread-B5cgadZl.js.map +0 -1
  134. package/dist/src/__base_element/BaseHyperlink.d.ts +0 -20
  135. package/dist/src/tree-view/index.d.ts +0 -2
  136. package/dist/src/tree-view/tree-node.d.ts +0 -69
  137. package/dist/src/tree-view/tree-view.d.ts +0 -40
  138. package/dist/src/tree-view/wc-tree-view.d.ts +0 -6
  139. package/dist/test/tree-view.test.d.ts +0 -1
  140. package/dist/throttle-C7ZAPqtu.js +0 -24
  141. package/dist/throttle-C7ZAPqtu.js.map +0 -1
  142. package/src/__base_element/BaseHyperlink.ts +0 -42
  143. package/src/tree-view/demo/index.html +0 -57
  144. package/src/tree-view/index.ts +0 -2
  145. package/src/tree-view/tree-node.scss +0 -101
  146. package/src/tree-view/tree-node.ts +0 -268
  147. package/src/tree-view/tree-view.ts +0 -182
  148. package/src/tree-view/wc-tree-view.ts +0 -9
@@ -0,0 +1,102 @@
1
+ @use '../../scss/mixin';
2
+
3
+ @include mixin.base-styles;
4
+
5
+ :host {
6
+ display: block;
7
+
8
+ // M3 sidebar menu item sizing
9
+ --sidebar-menu-item-height: 3rem;
10
+ --sidebar-menu-item-icon-size: 1.25rem;
11
+ --sidebar-menu-item-border-radius: var(--global-shape-corner-full, 9999px);
12
+
13
+ // M3 color tokens
14
+ --sidebar-menu-item-label-color: var(--color-on-surface);
15
+ --sidebar-menu-item-icon-color: var(--color-on-surface-variant);
16
+ --sidebar-menu-item-selected-background: var(--color-secondary-container);
17
+ --sidebar-menu-item-selected-color: var(--color-on-secondary-container);
18
+ --sidebar-menu-item-focus-ring-color: var(--color-primary);
19
+
20
+ // M3 animation timing
21
+ --sidebar-menu-item-transition-duration: 200ms;
22
+ --sidebar-menu-item-transition-easing: cubic-bezier(0.4, 0, 0.2, 1);
23
+ }
24
+
25
+ .sidebar-menu-item {
26
+ position: relative;
27
+ display: flex;
28
+ align-items: center;
29
+ min-height: var(--sidebar-menu-item-height);
30
+ border-radius: var(--sidebar-menu-item-border-radius);
31
+ color: var(--_label-color);
32
+ cursor: pointer;
33
+ user-select: none;
34
+ text-decoration: none;
35
+ outline: none;
36
+
37
+ --_container-color: transparent;
38
+ --_container-opacity: 1;
39
+ --_label-color: var(--sidebar-menu-item-label-color);
40
+
41
+ @include mixin.get-typography(label-large);
42
+
43
+ &.selected {
44
+ --_container-color: var(--sidebar-menu-item-selected-background);
45
+ --_label-color: var(--sidebar-menu-item-selected-color);
46
+ }
47
+
48
+ &.disabled {
49
+ cursor: not-allowed;
50
+ opacity: 0.6;
51
+
52
+ .ripple {
53
+ display: none;
54
+ }
55
+ }
56
+ }
57
+
58
+ .sidebar-menu-item-content {
59
+ display: flex;
60
+ align-items: center;
61
+ gap: 0.25rem;
62
+ flex: 1;
63
+ min-height: var(--sidebar-menu-item-height);
64
+ padding-inline: 0.75rem;
65
+ color: inherit;
66
+ z-index: 1;
67
+ }
68
+
69
+ .background {
70
+ position: absolute;
71
+ inset: 0;
72
+ background-color: var(--_container-color);
73
+ opacity: var(--_container-opacity);
74
+ border-radius: inherit;
75
+ pointer-events: none;
76
+ }
77
+
78
+ .focus-ring {
79
+ z-index: 2;
80
+ --focus-ring-color: var(--sidebar-menu-item-focus-ring-color);
81
+ --focus-ring-container-shape-start-start: var(--sidebar-menu-item-border-radius);
82
+ --focus-ring-container-shape-start-end: var(--sidebar-menu-item-border-radius);
83
+ --focus-ring-container-shape-end-start: var(--sidebar-menu-item-border-radius);
84
+ --focus-ring-container-shape-end-end: var(--sidebar-menu-item-border-radius);
85
+ }
86
+
87
+ .ripple {
88
+ --ripple-pressed-color: var(--color-on-surface);
89
+ border-radius: inherit;
90
+ }
91
+
92
+ .sidebar-menu-item.selected .ripple {
93
+ --ripple-pressed-color: var(--sidebar-menu-item-selected-color);
94
+ }
95
+
96
+ .sidebar-menu-item-label {
97
+ flex: 1;
98
+ overflow: hidden;
99
+ text-overflow: ellipsis;
100
+ white-space: nowrap;
101
+ }
102
+
@@ -0,0 +1,151 @@
1
+ import { html, LitElement } from 'lit';
2
+ import { property, query } from 'lit/decorators.js';
3
+ import { classMap } from 'lit/directives/class-map.js';
4
+ import styles from './sidebar-menu-item.scss';
5
+
6
+ /**
7
+ * @label Sidebar Menu Item
8
+ * @tag wc-sidebar-menu-item
9
+ * @rawTag sidebar-menu-item
10
+ * @parentRawTag sidebar-menu
11
+ * @summary A sidebar menu item represents a selectable leaf item in the sidebar navigation tree.
12
+ *
13
+ * @example
14
+ * ```html
15
+ * <wc-sidebar-menu>
16
+ * <wc-sidebar-sub-menu label="Parent" expanded>
17
+ * <wc-sidebar-menu-item label="Child"></wc-sidebar-menu-item>
18
+ * </wc-sidebar-sub-menu>
19
+ * </wc-sidebar-menu>
20
+ * ```
21
+ * @tags navigation
22
+ */
23
+ export class SidebarMenuItem extends LitElement {
24
+ static styles = [styles];
25
+
26
+ /**
27
+ * The value used to identify this item when selected.
28
+ */
29
+ @property({ type: String, reflect: true })
30
+ value: string = '';
31
+
32
+ /**
33
+ * The display label for this item.
34
+ */
35
+ @property({ type: String, reflect: true })
36
+ label: string = '';
37
+
38
+ /**
39
+ * Optional icon name to display before the label.
40
+ */
41
+ @property({ type: String, reflect: true })
42
+ icon: string = '';
43
+
44
+ /**
45
+ * Optional hyperlink to navigate to on click.
46
+ */
47
+ @property({ type: String, reflect: true })
48
+ href: string = '';
49
+
50
+ /**
51
+ * Sets or retrieves the window or frame at which to target content.
52
+ */
53
+ @property({ type: String, reflect: true })
54
+ target: string = '_self';
55
+
56
+ /**
57
+ * If true, the user cannot interact with the item.
58
+ */
59
+ @property({ type: Boolean, reflect: true })
60
+ disabled: boolean = false;
61
+
62
+ /**
63
+ * Whether the item is currently selected.
64
+ */
65
+ @property({ type: Boolean, reflect: true })
66
+ selected: boolean = false;
67
+
68
+ /**
69
+ * The nesting depth level (set automatically by the parent sidebar-menu).
70
+ */
71
+ @property({ type: Number, reflect: true })
72
+ level: number = 0;
73
+
74
+ @query('.sidebar-menu-item-content')
75
+ private readonly _nativeElement!: HTMLElement | null;
76
+
77
+ override focus() {
78
+ this._nativeElement?.focus();
79
+ }
80
+
81
+ override blur() {
82
+ this._nativeElement?.blur();
83
+ }
84
+
85
+ private _onClick = () => {
86
+ if (this.disabled) return;
87
+
88
+ this.dispatchEvent(
89
+ new CustomEvent('sidebar-menu-item:click', {
90
+ bubbles: true,
91
+ composed: true,
92
+ detail: { value: this.value, label: this.label },
93
+ }),
94
+ );
95
+ };
96
+
97
+ override render() {
98
+ const classes = classMap({
99
+ 'sidebar-menu-item': true,
100
+ disabled: this.disabled,
101
+ selected: this.selected,
102
+ });
103
+
104
+ const content = html`
105
+ <wc-focus-ring class="focus-ring" for="item"></wc-focus-ring>
106
+ <div class="background"></div>
107
+ <wc-ripple class="ripple"></wc-ripple>
108
+ <div class="sidebar-menu-item-content">
109
+ ${this.icon ? html`<wc-icon name="${this.icon}"></wc-icon>` : ''}
110
+ <span class="sidebar-menu-item-label">${this.label}</span>
111
+ </div>
112
+ `;
113
+
114
+ if (this.href) {
115
+ return html`
116
+ <a
117
+ id="item"
118
+ href="${this.href}"
119
+ target="${this.target}"
120
+ class="${classes}"
121
+ aria-disabled="${this.disabled}"
122
+ tabindex="${this.disabled ? -1 : 0}"
123
+ @click="${this._onClick}"
124
+ >
125
+ ${content}
126
+ </a>
127
+ `;
128
+ }
129
+
130
+ return html`
131
+ <div
132
+ id="item"
133
+ class="${classes}"
134
+ role="treeitem"
135
+ aria-label="${this.label}"
136
+ aria-selected="${String(this.selected)}"
137
+ aria-disabled="${this.disabled}"
138
+ tabindex="${this.disabled ? -1 : 0}"
139
+ @click="${this._onClick}"
140
+ @keydown="${(e: KeyboardEvent) => {
141
+ if (e.key === 'Enter' || e.key === ' ') {
142
+ e.preventDefault();
143
+ this._onClick();
144
+ }
145
+ }}"
146
+ >
147
+ ${content}
148
+ </div>
149
+ `;
150
+ }
151
+ }
@@ -6,7 +6,7 @@
6
6
  display: block;
7
7
  }
8
8
 
9
- .tree-view {
9
+ .sidebar-menu {
10
10
  display: block;
11
11
  padding: var(--spacing-100, 0.5rem) 0;
12
12
  }
@@ -0,0 +1,182 @@
1
+ import { html, LitElement } from 'lit';
2
+ import { property } from 'lit/decorators.js';
3
+ import styles from './sidebar-menu.scss';
4
+ import { SidebarMenuItem } from './sidebar-menu-item.js';
5
+ import { SidebarSubMenu } from './sidebar-sub-menu.js';
6
+
7
+ type SidebarNode = SidebarMenuItem | SidebarSubMenu;
8
+
9
+ /**
10
+ * @label Sidebar Menu
11
+ * @tag wc-sidebar-menu
12
+ * @rawTag sidebar-menu
13
+ * @summary A sidebar menu is a hierarchical structure that provides nested levels of navigation. It supports keyboard navigation, single/multi select, and expandable items.
14
+ *
15
+ * @example
16
+ * ```html
17
+ * <wc-sidebar-menu>
18
+ * <wc-sidebar-sub-menu label="Parent" expanded>
19
+ * <wc-sidebar-menu-item label="Child 1"></wc-sidebar-menu-item>
20
+ * <wc-sidebar-menu-item label="Child 2"></wc-sidebar-menu-item>
21
+ * </wc-sidebar-sub-menu>
22
+ * </wc-sidebar-menu>
23
+ * ```
24
+ * @tags navigation
25
+ */
26
+ export class SidebarMenu extends LitElement {
27
+ static styles = [styles];
28
+
29
+ /**
30
+ * The value of the currently selected item.
31
+ */
32
+ @property({ type: String, attribute: 'selected-item', reflect: true })
33
+ selectedItem: string = '';
34
+
35
+ connectedCallback() {
36
+ super.connectedCallback();
37
+ this.addEventListener('sidebar-menu-item:click', this._onItemClick as EventListener);
38
+ this.addEventListener('keydown', this._onKeyDown);
39
+ this.setAttribute('role', 'tree');
40
+ }
41
+
42
+ updated(changedProps: Map<string, unknown>) {
43
+ super.updated(changedProps);
44
+
45
+ if (changedProps.has('selectedItem')) {
46
+ this._syncSelectedStateFromProperty();
47
+ }
48
+ }
49
+
50
+ disconnectedCallback() {
51
+ super.disconnectedCallback();
52
+ this.removeEventListener('sidebar-menu-item:click', this._onItemClick as EventListener);
53
+ this.removeEventListener('keydown', this._onKeyDown);
54
+ }
55
+
56
+ private _isSidebarNode(element: Element): element is SidebarNode {
57
+ const tag = element.tagName.toLowerCase();
58
+ return tag === 'wc-sidebar-menu-item' || tag === 'wc-sidebar-sub-menu';
59
+ }
60
+
61
+ private _getTopLevelItems(): SidebarNode[] {
62
+ return Array.from(this.children).filter(
63
+ el => this._isSidebarNode(el),
64
+ ) as SidebarNode[];
65
+ }
66
+
67
+ private _getChildNodes(item: SidebarSubMenu): SidebarNode[] {
68
+ return Array.from(item.children).filter(
69
+ child => this._isSidebarNode(child),
70
+ ) as SidebarNode[];
71
+ }
72
+
73
+ private _getAllVisibleItems(): SidebarNode[] {
74
+ const result: SidebarNode[] = [];
75
+ const collect = (items: SidebarNode[]) => {
76
+ items.forEach(item => {
77
+ result.push(item);
78
+ if (item instanceof SidebarSubMenu && item.expanded) {
79
+ collect(this._getChildNodes(item));
80
+ }
81
+ });
82
+ };
83
+ collect(this._getTopLevelItems());
84
+ return result;
85
+ }
86
+
87
+ private _onItemClick = (event: CustomEvent) => {
88
+ const item = event.target as SidebarNode;
89
+ if (item.disabled) return;
90
+
91
+ const value = event.detail?.value ?? item.value ?? item.label;
92
+ this.selectedItem = value;
93
+
94
+ // Update selected state on all items
95
+ this._updateSelectedState(value);
96
+
97
+ this.dispatchEvent(
98
+ new CustomEvent('sidebar-menu:change', {
99
+ bubbles: true,
100
+ composed: true,
101
+ detail: { value, item },
102
+ }),
103
+ );
104
+ };
105
+
106
+ private _updateSelectedState(selectedValue: string) {
107
+ const allItems = this._collectAllItems(this._getTopLevelItems());
108
+ allItems.forEach(item => {
109
+ const itemValue = item.value || item.label;
110
+ // eslint-disable-next-line no-param-reassign
111
+ item.selected = itemValue === selectedValue;
112
+ });
113
+ }
114
+
115
+ private _collectAllItems(items: SidebarNode[]): SidebarNode[] {
116
+ const result: SidebarNode[] = [];
117
+ items.forEach(item => {
118
+ result.push(item);
119
+ if (item instanceof SidebarSubMenu) {
120
+ result.push(...this._collectAllItems(this._getChildNodes(item)));
121
+ }
122
+ });
123
+ return result;
124
+ }
125
+
126
+ private _syncSelectedStateFromProperty() {
127
+ const allItems = this._collectAllItems(this._getTopLevelItems());
128
+ allItems.forEach(item => {
129
+ const itemValue = item.value || item.label;
130
+ item.selected = itemValue === this.selectedItem;
131
+ });
132
+ }
133
+
134
+ private _onKeyDown = (event: KeyboardEvent) => {
135
+ const allVisible = this._getAllVisibleItems();
136
+ const currentElement = event.composedPath().find(
137
+ target => target instanceof SidebarMenuItem || target instanceof SidebarSubMenu,
138
+ ) as SidebarNode | undefined;
139
+
140
+ if (!currentElement) {
141
+ return;
142
+ }
143
+
144
+ if (!allVisible.includes(currentElement)) {
145
+ return;
146
+ }
147
+
148
+ const currentIndex = allVisible.indexOf(currentElement);
149
+
150
+ if (event.key === 'ArrowDown') {
151
+ event.preventDefault();
152
+ const nextIndex = (currentIndex + 1) % allVisible.length;
153
+ allVisible[nextIndex].focus();
154
+ } else if (event.key === 'ArrowUp') {
155
+ event.preventDefault();
156
+ const prevIndex = currentIndex === 0 ? allVisible.length - 1 : currentIndex - 1;
157
+ allVisible[prevIndex].focus();
158
+ } else if (event.key === 'Enter' || event.key === ' ') {
159
+ event.preventDefault();
160
+ currentElement.click();
161
+ } else if (event.key === 'ArrowRight') {
162
+ event.preventDefault();
163
+ if (currentElement instanceof SidebarSubMenu && !currentElement.expanded) {
164
+ currentElement.expanded = true;
165
+ } else if (currentElement instanceof SidebarSubMenu) {
166
+ const children = this._getChildNodes(currentElement);
167
+ if (children.length > 0) {
168
+ children[0].focus();
169
+ }
170
+ }
171
+ } else if (event.key === 'ArrowLeft') {
172
+ event.preventDefault();
173
+ if (currentElement instanceof SidebarSubMenu && currentElement.expanded) {
174
+ currentElement.expanded = false;
175
+ }
176
+ }
177
+ };
178
+
179
+ override render() {
180
+ return html` <div class="sidebar-menu"><slot></slot></div> `;
181
+ }
182
+ }
@@ -0,0 +1,130 @@
1
+ @use '../../scss/mixin';
2
+
3
+ @include mixin.base-styles;
4
+
5
+ :host {
6
+ display: block;
7
+
8
+ --sidebar-menu-item-height: 3rem;
9
+ --sidebar-menu-item-border-radius: var(--global-shape-corner-full, 9999px);
10
+ --sidebar-menu-item-label-color: var(--color-on-surface);
11
+ --sidebar-menu-item-icon-color: var(--color-on-surface-variant);
12
+ --sidebar-menu-item-selected-background: var(--color-secondary-container);
13
+ --sidebar-menu-item-selected-color: var(--color-on-secondary-container);
14
+ --sidebar-menu-item-focus-ring-color: var(--color-primary);
15
+ }
16
+
17
+ .sidebar-sub-menu {
18
+ display: block;
19
+ }
20
+
21
+ .sidebar-sub-menu-inner {
22
+ position: relative;
23
+ display: flex;
24
+ align-items: center;
25
+ gap: 0.5rem;
26
+ min-height: var(--sidebar-menu-item-height);
27
+ cursor: pointer;
28
+ border-radius: var(--sidebar-menu-item-border-radius);
29
+ outline: none;
30
+ padding-inline-end: 0.75rem;
31
+ color: var(--_label-color);
32
+
33
+ --_container-color: transparent;
34
+ --_container-opacity: 1;
35
+ --_label-color: var(--sidebar-menu-item-label-color);
36
+
37
+ @include mixin.get-typography(label-large);
38
+
39
+ &.selected {
40
+ --_container-color: var(--sidebar-menu-item-selected-background);
41
+ --_label-color: var(--sidebar-menu-item-selected-color);
42
+ }
43
+
44
+ &.disabled {
45
+ cursor: not-allowed;
46
+ opacity: 0.6;
47
+
48
+ .ripple {
49
+ display: none;
50
+ }
51
+ }
52
+ }
53
+
54
+ .sidebar-sub-menu-content {
55
+ display: flex;
56
+ align-items: center;
57
+ gap: 0.25rem;
58
+ flex: 1;
59
+ min-height: var(--sidebar-menu-item-height);
60
+ color: inherit;
61
+ user-select: none;
62
+ text-decoration: none;
63
+ outline: none;
64
+ padding-inline: 0.75rem;
65
+ z-index: 1;
66
+ }
67
+
68
+ .background {
69
+ position: absolute;
70
+ inset: 0;
71
+ background-color: var(--_container-color);
72
+ opacity: var(--_container-opacity);
73
+ border-radius: inherit;
74
+ pointer-events: none;
75
+ }
76
+
77
+ .focus-ring {
78
+ z-index: 2;
79
+ --focus-ring-color: var(--sidebar-menu-item-focus-ring-color);
80
+ --focus-ring-container-shape-start-start: var(--sidebar-menu-item-border-radius);
81
+ --focus-ring-container-shape-start-end: var(--sidebar-menu-item-border-radius);
82
+ --focus-ring-container-shape-end-start: var(--sidebar-menu-item-border-radius);
83
+ --focus-ring-container-shape-end-end: var(--sidebar-menu-item-border-radius);
84
+ }
85
+
86
+ .ripple {
87
+ --ripple-pressed-color: var(--color-on-surface);
88
+ border-radius: inherit;
89
+ }
90
+
91
+ .sidebar-sub-menu-inner.selected .ripple {
92
+ --ripple-pressed-color: var(--sidebar-menu-item-selected-color);
93
+ }
94
+
95
+ .sidebar-sub-menu-label {
96
+ flex: 1;
97
+ overflow: hidden;
98
+ text-overflow: ellipsis;
99
+ white-space: nowrap;
100
+ }
101
+
102
+ .expand-icon {
103
+ display: flex;
104
+ align-items: center;
105
+ justify-content: center;
106
+ color: var(--sidebar-menu-item-icon-color);
107
+ flex-shrink: 0;
108
+ width: var(--sidebar-menu-item-height);
109
+ height: var(--sidebar-menu-item-height);
110
+ transition: transform var(--duration-medium1) var(--easing-standard);
111
+ }
112
+
113
+ :host([expanded]) .expand-icon {
114
+ transform: rotate(180deg);
115
+ }
116
+
117
+ .sidebar-sub-menu-children {
118
+ display: block;
119
+ overflow: hidden;
120
+ margin-left: var(--spacing-200);
121
+ max-height: 9999px;
122
+ opacity: 1;
123
+ transition: max-height var(--duration-medium1) var(--easing-standard),
124
+ opacity var(--duration-medium1) var(--easing-standard);
125
+ }
126
+
127
+ .sidebar-sub-menu-children.hidden {
128
+ max-height: 0;
129
+ opacity: 0;
130
+ }