@material/web 2.4.2-nightly.2fe7e22.0 → 2.4.2-nightly.3758f46.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 (198) hide show
  1. package/button/internal/button.d.ts +0 -4
  2. package/button/internal/button.js.map +1 -1
  3. package/checkbox/internal/checkbox.d.ts +2 -2
  4. package/checkbox/internal/checkbox.js.map +1 -1
  5. package/chips/internal/chip.d.ts +2 -0
  6. package/icon/internal/icon.d.ts +1 -1
  7. package/icon/internal/icon.js +1 -1
  8. package/icon/internal/icon.js.map +1 -1
  9. package/iconbutton/internal/icon-button.d.ts +0 -4
  10. package/iconbutton/internal/icon-button.js.map +1 -1
  11. package/internal/aria/aria.d.ts +1 -1
  12. package/internal/events/dispatch-hooks.js +31 -35
  13. package/internal/events/dispatch-hooks.js.map +1 -1
  14. package/labs/behaviors/form-associated.d.ts +0 -22
  15. package/labs/behaviors/form-associated.js +0 -11
  16. package/labs/behaviors/form-associated.js.map +1 -1
  17. package/labs/gb/components/button/_button-tokens.scss +30 -30
  18. package/labs/gb/components/button/button.css +1 -1
  19. package/labs/gb/components/button/button.css.map +1 -1
  20. package/labs/gb/components/button/button.cssresult.js +1 -1
  21. package/labs/gb/components/button/button.cssresult.js.map +1 -1
  22. package/labs/gb/components/button/button.d.ts +1 -16
  23. package/labs/gb/components/button/button.js +10 -33
  24. package/labs/gb/components/button/button.js.map +1 -1
  25. package/labs/gb/components/button/button.scss +25 -25
  26. package/labs/gb/components/button/md-button.d.ts +1 -1
  27. package/labs/gb/components/button/md-button.js +9 -9
  28. package/labs/gb/components/button/md-button.js.map +1 -1
  29. package/labs/gb/components/card/card.d.ts +1 -11
  30. package/labs/gb/components/card/card.js +6 -13
  31. package/labs/gb/components/card/card.js.map +1 -1
  32. package/labs/gb/components/card/md-card.js +6 -6
  33. package/labs/gb/components/card/md-card.js.map +1 -1
  34. package/labs/gb/components/checkbox/checkbox.css +1 -1
  35. package/labs/gb/components/checkbox/checkbox.css.map +1 -1
  36. package/labs/gb/components/checkbox/checkbox.cssresult.js +1 -1
  37. package/labs/gb/components/checkbox/checkbox.cssresult.js.map +1 -1
  38. package/labs/gb/components/checkbox/checkbox.d.ts +1 -16
  39. package/labs/gb/components/checkbox/checkbox.js +8 -31
  40. package/labs/gb/components/checkbox/checkbox.js.map +1 -1
  41. package/labs/gb/components/checkbox/checkbox.scss +13 -13
  42. package/labs/gb/components/checkbox/md-checkbox.d.ts +4 -4
  43. package/labs/gb/components/checkbox/md-checkbox.js +10 -10
  44. package/labs/gb/components/checkbox/md-checkbox.js.map +1 -1
  45. package/labs/gb/components/divider/divider.d.ts +1 -11
  46. package/labs/gb/components/divider/divider.js +4 -11
  47. package/labs/gb/components/divider/divider.js.map +1 -1
  48. package/labs/gb/components/fab/fab.d.ts +1 -16
  49. package/labs/gb/components/fab/fab.js +8 -31
  50. package/labs/gb/components/fab/fab.js.map +1 -1
  51. package/labs/gb/components/fab/md-fab.js +4 -4
  52. package/labs/gb/components/fab/md-fab.js.map +1 -1
  53. package/labs/gb/components/focus/focus-ring.js +1 -1
  54. package/labs/gb/components/focus/focus-ring.js.map +1 -1
  55. package/labs/gb/components/iconbutton/_icon-button-tokens.scss +202 -0
  56. package/labs/gb/components/iconbutton/icon-button.css +4 -0
  57. package/labs/gb/components/iconbutton/icon-button.css.map +1 -0
  58. package/labs/gb/components/iconbutton/icon-button.cssresult.d.ts +3 -0
  59. package/labs/gb/components/iconbutton/icon-button.cssresult.js +14 -0
  60. package/labs/gb/components/iconbutton/icon-button.cssresult.js.map +1 -0
  61. package/labs/gb/components/iconbutton/icon-button.d.ts +97 -0
  62. package/labs/gb/components/iconbutton/icon-button.js +122 -0
  63. package/labs/gb/components/iconbutton/icon-button.js.map +1 -0
  64. package/labs/gb/components/iconbutton/icon-button.scss +153 -0
  65. package/labs/gb/components/iconbutton/md-icon-button.d.ts +73 -0
  66. package/labs/gb/components/iconbutton/md-icon-button.js +176 -0
  67. package/labs/gb/components/iconbutton/md-icon-button.js.map +1 -0
  68. package/labs/gb/components/list/_list-tokens.scss +102 -0
  69. package/labs/gb/components/list/list.css +4 -0
  70. package/labs/gb/components/list/list.css.map +1 -0
  71. package/labs/gb/components/list/list.cssresult.d.ts +3 -0
  72. package/labs/gb/components/list/list.cssresult.js +14 -0
  73. package/labs/gb/components/list/list.cssresult.js.map +1 -0
  74. package/labs/gb/components/list/list.d.ts +103 -0
  75. package/labs/gb/components/list/list.js +109 -0
  76. package/labs/gb/components/list/list.js.map +1 -0
  77. package/labs/gb/components/list/list.scss +212 -0
  78. package/labs/gb/components/list/md-list-item.d.ts +44 -0
  79. package/labs/gb/components/list/md-list-item.js +122 -0
  80. package/labs/gb/components/list/md-list-item.js.map +1 -0
  81. package/labs/gb/components/list/md-list.d.ts +26 -0
  82. package/labs/gb/components/list/md-list.js +51 -0
  83. package/labs/gb/components/list/md-list.js.map +1 -0
  84. package/labs/gb/components/menu/_menu-tokens.scss +128 -0
  85. package/labs/gb/components/menu/md-menu-group.d.ts +26 -0
  86. package/labs/gb/components/menu/md-menu-group.js +65 -0
  87. package/labs/gb/components/menu/md-menu-group.js.map +1 -0
  88. package/labs/gb/components/menu/md-menu-item.d.ts +30 -0
  89. package/labs/gb/components/menu/md-menu-item.js +165 -0
  90. package/labs/gb/components/menu/md-menu-item.js.map +1 -0
  91. package/labs/gb/components/menu/md-menu.d.ts +28 -0
  92. package/labs/gb/components/menu/md-menu.js +141 -0
  93. package/labs/gb/components/menu/md-menu.js.map +1 -0
  94. package/labs/gb/components/menu/menu.css +4 -0
  95. package/labs/gb/components/menu/menu.css.map +1 -0
  96. package/labs/gb/components/menu/menu.cssresult.d.ts +3 -0
  97. package/labs/gb/components/menu/menu.cssresult.js +14 -0
  98. package/labs/gb/components/menu/menu.cssresult.js.map +1 -0
  99. package/labs/gb/components/menu/menu.d.ts +117 -0
  100. package/labs/gb/components/menu/menu.js +107 -0
  101. package/labs/gb/components/menu/menu.js.map +1 -0
  102. package/labs/gb/components/menu/menu.scss +171 -0
  103. package/labs/gb/components/radio/md-radio.d.ts +4 -4
  104. package/labs/gb/components/radio/md-radio.js +11 -11
  105. package/labs/gb/components/radio/md-radio.js.map +1 -1
  106. package/labs/gb/components/radio/radio.css +1 -1
  107. package/labs/gb/components/radio/radio.css.map +1 -1
  108. package/labs/gb/components/radio/radio.cssresult.js +1 -1
  109. package/labs/gb/components/radio/radio.cssresult.js.map +1 -1
  110. package/labs/gb/components/radio/radio.d.ts +1 -14
  111. package/labs/gb/components/radio/radio.js +8 -23
  112. package/labs/gb/components/radio/radio.js.map +1 -1
  113. package/labs/gb/components/radio/radio.scss +4 -5
  114. package/labs/gb/components/ripple/ripple.d.ts +1 -10
  115. package/labs/gb/components/ripple/ripple.js +28 -32
  116. package/labs/gb/components/ripple/ripple.js.map +1 -1
  117. package/labs/gb/components/shared/directives.d.ts +93 -0
  118. package/labs/gb/components/shared/directives.js +111 -0
  119. package/labs/gb/components/shared/directives.js.map +1 -0
  120. package/labs/gb/components/shared/has-slotted.d.ts +10 -0
  121. package/labs/gb/components/shared/has-slotted.js +19 -0
  122. package/labs/gb/components/shared/has-slotted.js.map +1 -0
  123. package/labs/gb/components/shared/pseudo-classes.d.ts +7 -0
  124. package/labs/gb/components/shared/pseudo-classes.js +9 -0
  125. package/labs/gb/components/shared/pseudo-classes.js.map +1 -1
  126. package/labs/gb/components/splitbutton/_split-button-tokens.scss +135 -0
  127. package/labs/gb/components/splitbutton/md-split-button.d.ts +26 -0
  128. package/labs/gb/components/splitbutton/md-split-button.js +119 -0
  129. package/labs/gb/components/splitbutton/md-split-button.js.map +1 -0
  130. package/labs/gb/components/splitbutton/split-button.css +4 -0
  131. package/labs/gb/components/splitbutton/split-button.css.map +1 -0
  132. package/labs/gb/components/splitbutton/split-button.cssresult.d.ts +3 -0
  133. package/labs/gb/components/splitbutton/split-button.cssresult.js +14 -0
  134. package/labs/gb/components/splitbutton/split-button.cssresult.js.map +1 -0
  135. package/labs/gb/components/splitbutton/split-button.d.ts +47 -0
  136. package/labs/gb/components/splitbutton/split-button.js +46 -0
  137. package/labs/gb/components/splitbutton/split-button.js.map +1 -0
  138. package/labs/gb/components/splitbutton/split-button.scss +164 -0
  139. package/labs/gb/components/switch/_switch-tokens.scss +56 -0
  140. package/labs/gb/components/switch/md-switch.d.ts +66 -0
  141. package/labs/gb/components/switch/md-switch.js +162 -0
  142. package/labs/gb/components/switch/md-switch.js.map +1 -0
  143. package/labs/gb/components/switch/switch.css +4 -0
  144. package/labs/gb/components/switch/switch.css.map +1 -0
  145. package/labs/gb/components/switch/switch.cssresult.d.ts +3 -0
  146. package/labs/gb/components/switch/switch.cssresult.js +14 -0
  147. package/labs/gb/components/switch/switch.cssresult.js.map +1 -0
  148. package/labs/gb/components/switch/switch.d.ts +54 -0
  149. package/labs/gb/components/switch/switch.js +85 -0
  150. package/labs/gb/components/switch/switch.js.map +1 -0
  151. package/labs/gb/components/switch/switch.scss +109 -0
  152. package/labs/gb/styles/icon/md-icon.css +1 -1
  153. package/labs/gb/styles/icon/md-icon.css.map +1 -1
  154. package/labs/gb/styles/icon/md-icon.cssresult.js +1 -1
  155. package/labs/gb/styles/icon/md-icon.cssresult.js.map +1 -1
  156. package/labs/gb/styles/icon/md-icon.d.ts +20 -0
  157. package/labs/gb/styles/icon/md-icon.js +24 -0
  158. package/labs/gb/styles/icon/md-icon.js.map +1 -0
  159. package/labs/gb/styles/icon/md-icon.scss +2 -1
  160. package/labs/gb/styles/m3.css +5 -2
  161. package/labs/gb/styles/m3.css.map +1 -1
  162. package/labs/gb/styles/m3.cssresult.js +5 -2
  163. package/labs/gb/styles/m3.cssresult.js.map +1 -1
  164. package/labs/gb/styles/m3.scss +1 -0
  165. package/labs/gb/styles/space/md-space-tokens.css +4 -0
  166. package/labs/gb/styles/space/md-space-tokens.css.map +1 -0
  167. package/labs/gb/styles/space/md-space-tokens.cssresult.d.ts +3 -0
  168. package/labs/gb/styles/space/md-space-tokens.cssresult.js +14 -0
  169. package/labs/gb/styles/space/md-space-tokens.cssresult.js.map +1 -0
  170. package/labs/gb/styles/space/md-space-tokens.scss +28 -0
  171. package/labs/gb/styles/tailwind.css +4 -0
  172. package/labs/gb/styles/tailwind.css.map +1 -0
  173. package/labs/gb/styles/tailwind.cssresult.d.ts +3 -0
  174. package/labs/gb/styles/tailwind.cssresult.js +14 -0
  175. package/labs/gb/styles/tailwind.cssresult.js.map +1 -0
  176. package/labs/gb/styles/tailwind.scss +250 -0
  177. package/labs/gb/styles/typography/internal/_typography-tokens.scss +85 -16
  178. package/labs/gb/styles/typography/md-typography-tokens.css +1 -1
  179. package/labs/gb/styles/typography/md-typography-tokens.css.map +1 -1
  180. package/labs/gb/styles/typography/md-typography-tokens.cssresult.js +1 -1
  181. package/labs/gb/styles/typography/md-typography-tokens.cssresult.js.map +1 -1
  182. package/list/internal/listitem/list-item.d.ts +2 -0
  183. package/menu/internal/menuitem/menu-item.d.ts +2 -0
  184. package/package.json +7 -3
  185. package/radio/internal/radio.d.ts +0 -2
  186. package/radio/internal/radio.js.map +1 -1
  187. package/select/internal/select.d.ts +2 -2
  188. package/select/internal/select.js.map +1 -1
  189. package/select/internal/selectoption/select-option.d.ts +2 -0
  190. package/slider/internal/slider.d.ts +0 -2
  191. package/slider/internal/slider.js.map +1 -1
  192. package/switch/internal/_switch.scss +1 -0
  193. package/switch/internal/switch-styles.css +1 -1
  194. package/switch/internal/switch-styles.css.map +1 -1
  195. package/switch/internal/switch-styles.cssresult.js +1 -1
  196. package/switch/internal/switch-styles.cssresult.js.map +1 -1
  197. package/switch/internal/switch.d.ts +0 -2
  198. package/switch/internal/switch.js.map +1 -1
@@ -0,0 +1,141 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { __decorate } from "tslib";
7
+ import { ContextProvider } from '@lit/context';
8
+ import { css, html, LitElement } from 'lit';
9
+ import { customElement, property } from 'lit/decorators.js';
10
+ import { internals, mixinElementInternals, } from '../../../behaviors/element-internals.js';
11
+ import { mixinFocusable } from '../../../behaviors/focusable.js';
12
+ import menuStyles from './menu.css' with { type: 'css' }; // github-only
13
+ // import {styles as menuStyles} from './menu.cssresult.js'; // google3-only
14
+ import { menu, MENU_COLORS, menuContext } from './menu.js';
15
+ // Separate variable needed for closure.
16
+ const baseClass = mixinElementInternals(mixinFocusable(LitElement));
17
+ /**
18
+ * A Material Design menu component.
19
+ */
20
+ let Menu = class Menu extends baseClass {
21
+ get items() {
22
+ return Array.from(this.itemsSet).sort((a, b) => {
23
+ return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_PRECEDING
24
+ ? 1
25
+ : -1;
26
+ });
27
+ }
28
+ constructor() {
29
+ super();
30
+ this.color = MENU_COLORS.standard;
31
+ this.itemsSet = new Set();
32
+ this[internals].role = 'menu';
33
+ this.addController(new ContextProvider(this, {
34
+ context: menuContext,
35
+ initialValue: {
36
+ menu: this,
37
+ getItems: () => this.items,
38
+ itemConnected: (item) => {
39
+ this.itemsSet.add(item);
40
+ },
41
+ itemDisconnected: (item) => {
42
+ this.itemsSet.delete(item);
43
+ },
44
+ },
45
+ }));
46
+ // TODO: move event listeners to setupMenu()
47
+ // Handle keyboard navigation
48
+ this.addEventListener('keydown', (event) => {
49
+ if (event.key === 'Tab') {
50
+ event.preventDefault();
51
+ this.hidePopover();
52
+ return;
53
+ }
54
+ const items = this.items.filter((item) => !item.matches(':disabled,[disabled]'));
55
+ const index = items.findIndex((item) => item.matches(':focus-within'));
56
+ if (index === -1 && items.length > 0) {
57
+ // If no item is focused, focus the first one on arrow key
58
+ if ([
59
+ 'ArrowDown',
60
+ 'ArrowRight',
61
+ 'ArrowUp',
62
+ 'ArrowLeft',
63
+ 'Home',
64
+ 'End',
65
+ ].includes(event.key)) {
66
+ event.preventDefault();
67
+ items[0].focus();
68
+ }
69
+ return;
70
+ }
71
+ switch (event.key) {
72
+ case 'ArrowDown':
73
+ case 'ArrowRight':
74
+ event.preventDefault();
75
+ if (index < items.length - 1) {
76
+ items[index + 1].focus();
77
+ }
78
+ else {
79
+ items[0].focus();
80
+ }
81
+ break;
82
+ case 'ArrowUp':
83
+ case 'ArrowLeft':
84
+ event.preventDefault();
85
+ if (index > 0) {
86
+ items[index - 1].focus();
87
+ }
88
+ else {
89
+ items[items.length - 1].focus();
90
+ }
91
+ break;
92
+ case 'Home':
93
+ event.preventDefault();
94
+ items[0].focus();
95
+ break;
96
+ case 'End':
97
+ event.preventDefault();
98
+ items[items.length - 1].focus();
99
+ break;
100
+ default:
101
+ break;
102
+ }
103
+ });
104
+ // Handle focus on open
105
+ this.addEventListener('toggle', (event) => {
106
+ if (event.newState === 'open') {
107
+ this.previouslyFocused = event.source;
108
+ // Focus the first non-disabled item
109
+ setTimeout(() => {
110
+ this.items
111
+ .find((item) => !item.matches(':disabled,.disabled,[disabled]'))
112
+ ?.focus();
113
+ });
114
+ }
115
+ else {
116
+ this.previouslyFocused?.focus();
117
+ this.previouslyFocused = undefined;
118
+ }
119
+ });
120
+ }
121
+ connectedCallback() {
122
+ super.connectedCallback();
123
+ // Set popover behavior in connectedCallback since constructor may not
124
+ // sprout attributes.
125
+ this.popover = 'auto';
126
+ }
127
+ render() {
128
+ return html `<div part="menu" class="${menu({ color: this.color })} menu-host">
129
+ <slot></slot>
130
+ </div>`;
131
+ }
132
+ };
133
+ Menu.styles = [menuStyles, css ``];
134
+ __decorate([
135
+ property()
136
+ ], Menu.prototype, "color", void 0);
137
+ Menu = __decorate([
138
+ customElement('md-menu')
139
+ ], Menu);
140
+ export { Menu };
141
+ //# sourceMappingURL=md-menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"md-menu.js","sourceRoot":"","sources":["md-menu.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {ContextProvider} from '@lit/context';\nimport {css, CSSResultOrNative, html, LitElement} from 'lit';\nimport {customElement, property} from 'lit/decorators.js';\nimport {\n internals,\n mixinElementInternals,\n} from '../../../behaviors/element-internals.js';\nimport {mixinFocusable} from '../../../behaviors/focusable.js';\n\nimport menuStyles from './menu.css' with {type: 'css'}; // github-only\n// import {styles as menuStyles} from './menu.cssresult.js'; // google3-only\n\nimport {menu, MENU_COLORS, menuContext, type MenuColor} from './menu.js';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n /** A Material Design menu component. */\n 'md-menu': Menu;\n }\n}\n\n// Separate variable needed for closure.\nconst baseClass = mixinElementInternals(mixinFocusable(LitElement));\n\n/**\n * A Material Design menu component.\n */\n@customElement('md-menu')\nexport class Menu extends baseClass {\n static override styles: CSSResultOrNative[] = [menuStyles, css``];\n\n @property() color: MenuColor = MENU_COLORS.standard;\n\n get items(): HTMLElement[] {\n return Array.from(this.itemsSet).sort((a, b) => {\n return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_PRECEDING\n ? 1\n : -1;\n });\n }\n\n private previouslyFocused?: HTMLElement;\n private readonly itemsSet = new Set<HTMLElement>();\n\n constructor() {\n super();\n this[internals].role = 'menu';\n this.addController(\n new ContextProvider(this, {\n context: menuContext,\n initialValue: {\n menu: this,\n getItems: () => this.items,\n itemConnected: (item: HTMLElement) => {\n this.itemsSet.add(item);\n },\n itemDisconnected: (item: HTMLElement) => {\n this.itemsSet.delete(item);\n },\n },\n }),\n );\n\n // TODO: move event listeners to setupMenu()\n // Handle keyboard navigation\n this.addEventListener('keydown', (event: KeyboardEvent) => {\n if (event.key === 'Tab') {\n event.preventDefault();\n this.hidePopover();\n return;\n }\n\n const items = this.items.filter(\n (item) => !item.matches(':disabled,[disabled]'),\n );\n const index = items.findIndex((item) => item.matches(':focus-within'));\n if (index === -1 && items.length > 0) {\n // If no item is focused, focus the first one on arrow key\n if (\n [\n 'ArrowDown',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowLeft',\n 'Home',\n 'End',\n ].includes(event.key)\n ) {\n event.preventDefault();\n items[0].focus();\n }\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowRight':\n event.preventDefault();\n if (index < items.length - 1) {\n items[index + 1].focus();\n } else {\n items[0].focus();\n }\n break;\n case 'ArrowUp':\n case 'ArrowLeft':\n event.preventDefault();\n if (index > 0) {\n items[index - 1].focus();\n } else {\n items[items.length - 1].focus();\n }\n break;\n case 'Home':\n event.preventDefault();\n items[0].focus();\n break;\n case 'End':\n event.preventDefault();\n items[items.length - 1].focus();\n break;\n default:\n break;\n }\n });\n\n // Handle focus on open\n this.addEventListener(\n 'toggle',\n (event: ToggleEvent & {source?: Element | null}) => {\n if (event.newState === 'open') {\n this.previouslyFocused = event.source as HTMLElement;\n // Focus the first non-disabled item\n setTimeout(() => {\n this.items\n .find((item) => !item.matches(':disabled,.disabled,[disabled]'))\n ?.focus();\n });\n } else {\n this.previouslyFocused?.focus();\n this.previouslyFocused = undefined;\n }\n },\n );\n }\n\n override connectedCallback() {\n super.connectedCallback();\n // Set popover behavior in connectedCallback since constructor may not\n // sprout attributes.\n this.popover = 'auto';\n }\n\n protected override render() {\n return html`<div part=\"menu\" class=\"${menu({color: this.color})} menu-host\">\n <slot></slot>\n </div>`;\n }\n}\n"]}
@@ -0,0 +1,4 @@
1
+ /*!
2
+ * Copyright 2026 Google LLC
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */@layer md.sys, md.comp.ripple, md.comp.focus-ring, md.comp.divider;@layer md.comp.menu{.menu{--container-color: var(--md-sys-color-surface-container-low);--container-elevation: var(--md-sys-elevation-shadow-2);--container-shape: var(--md-sys-shape-corner-lg);--gap: 2px;--group-padding: 2px;--group-shape: var(--md-sys-shape-corner-sm);--section-label-text-color: var(--md-sys-color-on-surface-variant)}.menu.menu-vibrant{--container-color: var(--md-sys-color-tertiary-container);--menu-vibrant: true}.menu{flex-direction:column;box-shadow:var(--container-elevation);border-radius:var(--container-shape);background-color:var(--container-color);padding-block:var(--group-padding)}.menu:popover-open,.menu.menu-host{display:flex}.menu:popover-open,:host(:popover-open):has(.menu.menu-host){position-area:end span-end;border:none}:host(:popover-open):has(.menu.menu-host){overflow:visible;background:none;padding:0}.menu.menu-host{overflow:auto}.menu .divider,.menu ::slotted(.divider){margin:8px 16px}.menu-item{--between-space: 12px;--bottom-space: 8px;--container-color: transparent;--height: 44px;--inner-corner-corner-size: none;--label-text-color: var(--md-sys-color-on-surface);--label-text: var(--md-sys-typescale-label-lg);--label-text-tracking: var(--md-sys-typescale-label-lg-tracking);--leading-icon-color: var(--md-sys-color-on-surface-variant);--leading-icon-size: 20px;--leading-space: 16px;--shape: var(--md-sys-shape-corner-xs);--supporting-text-color: var(--md-sys-color-on-surface-variant);--supporting-text: var(--md-sys-typescale-body-sm);--supporting-text-tracking: var(--md-sys-typescale-body-sm-tracking);--top-space: 8px;--trailing-icon-color: var(--md-sys-color-on-surface-variant);--trailing-icon-size: 20px;--trailing-space: 16px;--trailing-supporting-text-color: var(--md-sys-color-on-surface-variant);--trailing-supporting-text: var(--md-sys-typescale-label-lg);--trailing-supporting-text-tracking: var(--md-sys-typescale-label-lg-tracking)}.menu-item:first-child{--inner-corner-corner-size: var(--md-sys-shape-corner-xs);--shape: var(--md-sys-shape-corner-md)}.menu-item:last-child{--inner-corner-corner-size: var(--md-sys-shape-corner-xs);--shape: var(--md-sys-shape-corner-md)}@container style(--menu-vibrant: true){.menu-item{--label-text-color: var(--md-sys-color-on-tertiary-container);--leading-icon-color: var(--md-sys-color-on-tertiary-container);--supporting-text-color: var(--md-sys-color-on-tertiary-container);--trailing-icon-color: var(--md-sys-color-on-tertiary-container);--trailing-supporting-text-color: var(--md-sys-color-on-tertiary-container)}.menu-item:where(:hover,.hover){--leading-icon-color: var(--md-sys-color-tertiary);--trailing-icon-color: var(--md-sys-color-tertiary)}.menu-item:where(:focus-within,.focus){--leading-icon-color: var(--md-sys-color-tertiary);--trailing-icon-color: var(--md-sys-color-tertiary)}.menu-item:where(:active,.active){--leading-icon-color: var(--md-sys-color-tertiary);--trailing-icon-color: var(--md-sys-color-tertiary)}}.menu-item:is(:checked,.checked){--container-color: var(--md-sys-color-tertiary-container);--label-text-color: var(--md-sys-color-on-tertiary-container);--leading-icon-color: var(--md-sys-color-on-tertiary-container);--shape: var(--md-sys-shape-corner-md);--supporting-text-color: var(--md-sys-color-on-tertiary-container);--trailing-icon-color: var(--md-sys-color-on-tertiary-container);--trailing-supporting-text-color: var(--md-sys-color-on-tertiary-container)}@container style(--menu-vibrant: true){.menu-item:is(:checked,.checked){--container-color: var(--md-sys-color-tertiary);--label-text-color: var(--md-sys-color-on-tertiary);--leading-icon-color: var(--md-sys-color-on-tertiary);--supporting-text-color: var(--md-sys-color-on-tertiary);--trailing-icon-color: var(--md-sys-color-on-tertiary);--trailing-supporting-text-color: var(--md-sys-color-on-tertiary)}}.menu-item:is(:disabled,.disabled){--label-text-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--leading-icon-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--supporting-text-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--trailing-icon-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--trailing-supporting-text-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%)}@container style(--menu-vibrant: true){.menu-item:is(:disabled,.disabled){--label-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--leading-icon-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--supporting-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--trailing-icon-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--trailing-supporting-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%)}}.menu-item:is(:disabled,.disabled):where(:checked,.checked){--container-color: hsl(from var(--md-sys-color-tertiary-container) h s l / 38%);--label-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--leading-icon-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--supporting-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--trailing-icon-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--trailing-supporting-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%)}.menu-item{position:relative;isolation:isolate;display:flex;align-items:center;user-select:none;box-sizing:border-box;gap:var(--between-space);min-height:calc(var(--height) + 4px);border-radius:var(--shape);padding-block:var(--top-space) var(--bottom-space);padding-inline:var(--leading-space) var(--trailing-space);background-image:none;outline:none;color:var(--label-text-color);font:var(--label-text);letter-spacing:var(--label-text-tracking)}.menu-item::before{display:flex;content:"";position:absolute;inset:2px 4px;z-index:-1;border-radius:inherit;background-color:var(--container-color);background-image:var(--ripple);animation:var(--ripple-animation),var(--focus-ring-animation);transition:var(--ripple-transition);outline:var(--focus-ring-outline);outline-offset:var(--focus-ring-offset)}.menu-item:not(:disabled,.disabled){cursor:pointer}.menu-item .menu-item-content{display:flex;flex-direction:column;flex:1}.menu-item .menu-item-supporting-text{color:var(--supporting-text-color);font:var(--supporting-text);letter-spacing:var(--supporting-text-tracking)}.menu-item .menu-item-trailing-text{color:var(--trailing-supporting-text-color);font:var(--trailing-supporting-text);letter-spacing:var(--trailing-supporting-text-tracking)}.menu-item .menu-item-leading,.menu-item .menu-item-trailing{display:flex;align-items:center;gap:8px}.menu-item .menu-item-leading{--md-icon-color: var(--leading-icon-color);--md-icon-size: var(--leading-icon-size)}.menu-item .menu-item-trailing{--md-icon-color: var(--trailing-icon-color);--md-icon-size: var(--trailing-icon-size)}}/*# sourceMappingURL=menu.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sourceRoot":"","sources":["menu.scss","_menu-tokens.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAAA,GASA,mEACA,oBAEI,MCNF,6DACA,wDACA,iDACA,WACA,qBACA,6CACA,mEDGE,mBCSF,0DDPI,qBAGF,MACE,sBACA,sCACA,qCACA,wCACA,mCAGF,mCAEE,aAGF,6DAEE,2BACA,YAGF,0CACE,iBACA,gBACA,UAGF,gBACE,cAGF,yCAEE,gBAKF,WC5BF,sBACA,oBACA,+BACA,eACA,iCACA,mDACA,+CACA,iEACA,6DACA,0BACA,sBACA,uCACA,gEACA,mDACA,qEACA,iBACA,8DACA,2BACA,uBACA,yEACA,6DACA,+EDUE,uBCNF,0DACA,uCDQE,sBCJF,0DACA,uCDME,uCACE,WCHJ,8DACA,gEACA,mEACA,iEACA,4EDEI,gCCEJ,mDACA,2FAIA,mDACA,oDDFI,kCCMJ,mDACA,qDDFE,iCCMF,0DACA,8DACA,gEACA,uCACA,mEACA,iEACA,4EDVI,uCAFF,iCCgBF,gDACA,oDACA,sDACA,yDACA,uDACA,mEDdE,mCCkBF,yEACA,2EACA,8EACA,4EACA,uFDpBI,uCAFF,mCC0BF,oFACA,sFACA,yFACA,uFACA,mGDzBI,4DC6BJ,gFACA,oFACA,sFACA,yFACA,uFACA,kGD7BE,WACE,kBACA,kBACA,aACA,mBACA,iBACA,sBACA,yBACA,qCACA,2BACA,mDACA,0DACA,sBACA,aACA,8BACA,uBACA,0CAGF,mBACE,aACA,WACA,kBACA,cACA,WACA,sBACA,wCACA,+BACA,8DACA,oCACA,kCACA,wCAGF,oCACE,eAGF,8BACE,aACA,sBACA,OAGF,sCACE,mCACA,4BACA,+CAGF,oCACE,4CACA,qCACA,wDAGF,6DAEE,aACA,mBACA,QAGF,8BACE,2CACA,yCAGF,+BACE,4CACA","file":"menu.css"}
@@ -0,0 +1,3 @@
1
+ export declare const styles: import("lit").CSSResult;
2
+ declare const _default: CSSStyleSheet;
3
+ export default _default;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ // Generated stylesheet for ./labs/gb/components/menu/menu.css.
7
+ import { css } from 'lit';
8
+ export const styles = css `/*!
9
+ * Copyright 2026 Google LLC
10
+ * SPDX-License-Identifier: Apache-2.0
11
+ */@layer md.sys, md.comp.ripple, md.comp.focus-ring, md.comp.divider;@layer md.comp.menu{.menu{--container-color: var(--md-sys-color-surface-container-low);--container-elevation: var(--md-sys-elevation-shadow-2);--container-shape: var(--md-sys-shape-corner-lg);--gap: 2px;--group-padding: 2px;--group-shape: var(--md-sys-shape-corner-sm);--section-label-text-color: var(--md-sys-color-on-surface-variant)}.menu.menu-vibrant{--container-color: var(--md-sys-color-tertiary-container);--menu-vibrant: true}.menu{flex-direction:column;box-shadow:var(--container-elevation);border-radius:var(--container-shape);background-color:var(--container-color);padding-block:var(--group-padding)}.menu:popover-open,.menu.menu-host{display:flex}.menu:popover-open,:host(:popover-open):has(.menu.menu-host){position-area:end span-end;border:none}:host(:popover-open):has(.menu.menu-host){overflow:visible;background:none;padding:0}.menu.menu-host{overflow:auto}.menu .divider,.menu ::slotted(.divider){margin:8px 16px}.menu-item{--between-space: 12px;--bottom-space: 8px;--container-color: transparent;--height: 44px;--inner-corner-corner-size: none;--label-text-color: var(--md-sys-color-on-surface);--label-text: var(--md-sys-typescale-label-lg);--label-text-tracking: var(--md-sys-typescale-label-lg-tracking);--leading-icon-color: var(--md-sys-color-on-surface-variant);--leading-icon-size: 20px;--leading-space: 16px;--shape: var(--md-sys-shape-corner-xs);--supporting-text-color: var(--md-sys-color-on-surface-variant);--supporting-text: var(--md-sys-typescale-body-sm);--supporting-text-tracking: var(--md-sys-typescale-body-sm-tracking);--top-space: 8px;--trailing-icon-color: var(--md-sys-color-on-surface-variant);--trailing-icon-size: 20px;--trailing-space: 16px;--trailing-supporting-text-color: var(--md-sys-color-on-surface-variant);--trailing-supporting-text: var(--md-sys-typescale-label-lg);--trailing-supporting-text-tracking: var(--md-sys-typescale-label-lg-tracking)}.menu-item:first-child{--inner-corner-corner-size: var(--md-sys-shape-corner-xs);--shape: var(--md-sys-shape-corner-md)}.menu-item:last-child{--inner-corner-corner-size: var(--md-sys-shape-corner-xs);--shape: var(--md-sys-shape-corner-md)}@container style(--menu-vibrant: true){.menu-item{--label-text-color: var(--md-sys-color-on-tertiary-container);--leading-icon-color: var(--md-sys-color-on-tertiary-container);--supporting-text-color: var(--md-sys-color-on-tertiary-container);--trailing-icon-color: var(--md-sys-color-on-tertiary-container);--trailing-supporting-text-color: var(--md-sys-color-on-tertiary-container)}.menu-item:where(:hover,.hover){--leading-icon-color: var(--md-sys-color-tertiary);--trailing-icon-color: var(--md-sys-color-tertiary)}.menu-item:where(:focus-within,.focus){--leading-icon-color: var(--md-sys-color-tertiary);--trailing-icon-color: var(--md-sys-color-tertiary)}.menu-item:where(:active,.active){--leading-icon-color: var(--md-sys-color-tertiary);--trailing-icon-color: var(--md-sys-color-tertiary)}}.menu-item:is(:checked,.checked){--container-color: var(--md-sys-color-tertiary-container);--label-text-color: var(--md-sys-color-on-tertiary-container);--leading-icon-color: var(--md-sys-color-on-tertiary-container);--shape: var(--md-sys-shape-corner-md);--supporting-text-color: var(--md-sys-color-on-tertiary-container);--trailing-icon-color: var(--md-sys-color-on-tertiary-container);--trailing-supporting-text-color: var(--md-sys-color-on-tertiary-container)}@container style(--menu-vibrant: true){.menu-item:is(:checked,.checked){--container-color: var(--md-sys-color-tertiary);--label-text-color: var(--md-sys-color-on-tertiary);--leading-icon-color: var(--md-sys-color-on-tertiary);--supporting-text-color: var(--md-sys-color-on-tertiary);--trailing-icon-color: var(--md-sys-color-on-tertiary);--trailing-supporting-text-color: var(--md-sys-color-on-tertiary)}}.menu-item:is(:disabled,.disabled){--label-text-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--leading-icon-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--supporting-text-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--trailing-icon-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--trailing-supporting-text-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%)}@container style(--menu-vibrant: true){.menu-item:is(:disabled,.disabled){--label-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--leading-icon-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--supporting-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--trailing-icon-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--trailing-supporting-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%)}}.menu-item:is(:disabled,.disabled):where(:checked,.checked){--container-color: hsl(from var(--md-sys-color-tertiary-container) h s l / 38%);--label-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--leading-icon-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--supporting-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--trailing-icon-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--trailing-supporting-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%)}.menu-item{position:relative;isolation:isolate;display:flex;align-items:center;user-select:none;box-sizing:border-box;gap:var(--between-space);min-height:calc(var(--height) + 4px);border-radius:var(--shape);padding-block:var(--top-space) var(--bottom-space);padding-inline:var(--leading-space) var(--trailing-space);background-image:none;outline:none;color:var(--label-text-color);font:var(--label-text);letter-spacing:var(--label-text-tracking)}.menu-item::before{display:flex;content:"";position:absolute;inset:2px 4px;z-index:-1;border-radius:inherit;background-color:var(--container-color);background-image:var(--ripple);animation:var(--ripple-animation),var(--focus-ring-animation);transition:var(--ripple-transition);outline:var(--focus-ring-outline);outline-offset:var(--focus-ring-offset)}.menu-item:not(:disabled,.disabled){cursor:pointer}.menu-item .menu-item-content{display:flex;flex-direction:column;flex:1}.menu-item .menu-item-supporting-text{color:var(--supporting-text-color);font:var(--supporting-text);letter-spacing:var(--supporting-text-tracking)}.menu-item .menu-item-trailing-text{color:var(--trailing-supporting-text-color);font:var(--trailing-supporting-text);letter-spacing:var(--trailing-supporting-text-tracking)}.menu-item .menu-item-leading,.menu-item .menu-item-trailing{display:flex;align-items:center;gap:8px}.menu-item .menu-item-leading{--md-icon-color: var(--leading-icon-color);--md-icon-size: var(--leading-icon-size)}.menu-item .menu-item-trailing{--md-icon-color: var(--trailing-icon-color);--md-icon-size: var(--trailing-icon-size)}}
12
+ `;
13
+ export default styles.styleSheet;
14
+ //# sourceMappingURL=menu.cssresult.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu.cssresult.js","sourceRoot":"","sources":["menu.cssresult.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,+DAA+D;AAC/D,OAAO,EAAC,GAAG,EAAC,MAAM,KAAK,CAAC;AACxB,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;CAIxB,CAAC;AACF,eAAe,MAAM,CAAC,UAAW,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n// Generated stylesheet for ./labs/gb/components/menu/menu.css.\nimport {css} from 'lit';\nexport const styles = css`/*!\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */@layer md.sys, md.comp.ripple, md.comp.focus-ring, md.comp.divider;@layer md.comp.menu{.menu{--container-color: var(--md-sys-color-surface-container-low);--container-elevation: var(--md-sys-elevation-shadow-2);--container-shape: var(--md-sys-shape-corner-lg);--gap: 2px;--group-padding: 2px;--group-shape: var(--md-sys-shape-corner-sm);--section-label-text-color: var(--md-sys-color-on-surface-variant)}.menu.menu-vibrant{--container-color: var(--md-sys-color-tertiary-container);--menu-vibrant: true}.menu{flex-direction:column;box-shadow:var(--container-elevation);border-radius:var(--container-shape);background-color:var(--container-color);padding-block:var(--group-padding)}.menu:popover-open,.menu.menu-host{display:flex}.menu:popover-open,:host(:popover-open):has(.menu.menu-host){position-area:end span-end;border:none}:host(:popover-open):has(.menu.menu-host){overflow:visible;background:none;padding:0}.menu.menu-host{overflow:auto}.menu .divider,.menu ::slotted(.divider){margin:8px 16px}.menu-item{--between-space: 12px;--bottom-space: 8px;--container-color: transparent;--height: 44px;--inner-corner-corner-size: none;--label-text-color: var(--md-sys-color-on-surface);--label-text: var(--md-sys-typescale-label-lg);--label-text-tracking: var(--md-sys-typescale-label-lg-tracking);--leading-icon-color: var(--md-sys-color-on-surface-variant);--leading-icon-size: 20px;--leading-space: 16px;--shape: var(--md-sys-shape-corner-xs);--supporting-text-color: var(--md-sys-color-on-surface-variant);--supporting-text: var(--md-sys-typescale-body-sm);--supporting-text-tracking: var(--md-sys-typescale-body-sm-tracking);--top-space: 8px;--trailing-icon-color: var(--md-sys-color-on-surface-variant);--trailing-icon-size: 20px;--trailing-space: 16px;--trailing-supporting-text-color: var(--md-sys-color-on-surface-variant);--trailing-supporting-text: var(--md-sys-typescale-label-lg);--trailing-supporting-text-tracking: var(--md-sys-typescale-label-lg-tracking)}.menu-item:first-child{--inner-corner-corner-size: var(--md-sys-shape-corner-xs);--shape: var(--md-sys-shape-corner-md)}.menu-item:last-child{--inner-corner-corner-size: var(--md-sys-shape-corner-xs);--shape: var(--md-sys-shape-corner-md)}@container style(--menu-vibrant: true){.menu-item{--label-text-color: var(--md-sys-color-on-tertiary-container);--leading-icon-color: var(--md-sys-color-on-tertiary-container);--supporting-text-color: var(--md-sys-color-on-tertiary-container);--trailing-icon-color: var(--md-sys-color-on-tertiary-container);--trailing-supporting-text-color: var(--md-sys-color-on-tertiary-container)}.menu-item:where(:hover,.hover){--leading-icon-color: var(--md-sys-color-tertiary);--trailing-icon-color: var(--md-sys-color-tertiary)}.menu-item:where(:focus-within,.focus){--leading-icon-color: var(--md-sys-color-tertiary);--trailing-icon-color: var(--md-sys-color-tertiary)}.menu-item:where(:active,.active){--leading-icon-color: var(--md-sys-color-tertiary);--trailing-icon-color: var(--md-sys-color-tertiary)}}.menu-item:is(:checked,.checked){--container-color: var(--md-sys-color-tertiary-container);--label-text-color: var(--md-sys-color-on-tertiary-container);--leading-icon-color: var(--md-sys-color-on-tertiary-container);--shape: var(--md-sys-shape-corner-md);--supporting-text-color: var(--md-sys-color-on-tertiary-container);--trailing-icon-color: var(--md-sys-color-on-tertiary-container);--trailing-supporting-text-color: var(--md-sys-color-on-tertiary-container)}@container style(--menu-vibrant: true){.menu-item:is(:checked,.checked){--container-color: var(--md-sys-color-tertiary);--label-text-color: var(--md-sys-color-on-tertiary);--leading-icon-color: var(--md-sys-color-on-tertiary);--supporting-text-color: var(--md-sys-color-on-tertiary);--trailing-icon-color: var(--md-sys-color-on-tertiary);--trailing-supporting-text-color: var(--md-sys-color-on-tertiary)}}.menu-item:is(:disabled,.disabled){--label-text-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--leading-icon-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--supporting-text-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--trailing-icon-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--trailing-supporting-text-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%)}@container style(--menu-vibrant: true){.menu-item:is(:disabled,.disabled){--label-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--leading-icon-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--supporting-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--trailing-icon-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--trailing-supporting-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%)}}.menu-item:is(:disabled,.disabled):where(:checked,.checked){--container-color: hsl(from var(--md-sys-color-tertiary-container) h s l / 38%);--label-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--leading-icon-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--supporting-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--trailing-icon-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%);--trailing-supporting-text-color: hsl(from var(--md-sys-color-on-tertiary-container) h s l / 38%)}.menu-item{position:relative;isolation:isolate;display:flex;align-items:center;user-select:none;box-sizing:border-box;gap:var(--between-space);min-height:calc(var(--height) + 4px);border-radius:var(--shape);padding-block:var(--top-space) var(--bottom-space);padding-inline:var(--leading-space) var(--trailing-space);background-image:none;outline:none;color:var(--label-text-color);font:var(--label-text);letter-spacing:var(--label-text-tracking)}.menu-item::before{display:flex;content:\"\";position:absolute;inset:2px 4px;z-index:-1;border-radius:inherit;background-color:var(--container-color);background-image:var(--ripple);animation:var(--ripple-animation),var(--focus-ring-animation);transition:var(--ripple-transition);outline:var(--focus-ring-outline);outline-offset:var(--focus-ring-offset)}.menu-item:not(:disabled,.disabled){cursor:pointer}.menu-item .menu-item-content{display:flex;flex-direction:column;flex:1}.menu-item .menu-item-supporting-text{color:var(--supporting-text-color);font:var(--supporting-text);letter-spacing:var(--supporting-text-tracking)}.menu-item .menu-item-trailing-text{color:var(--trailing-supporting-text-color);font:var(--trailing-supporting-text);letter-spacing:var(--trailing-supporting-text-tracking)}.menu-item .menu-item-leading,.menu-item .menu-item-trailing{display:flex;align-items:center;gap:8px}.menu-item .menu-item-leading{--md-icon-color: var(--leading-icon-color);--md-icon-size: var(--leading-icon-size)}.menu-item .menu-item-trailing{--md-icon-color: var(--trailing-icon-color);--md-icon-size: var(--trailing-icon-size)}}\n`;\nexport default styles.styleSheet!;\n"]}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { type ClassInfo } from 'lit/directives/class-map.js';
7
+ /** Menu context provided to menu items. */
8
+ export interface MenuContext {
9
+ /** The item's parent menu. */
10
+ readonly menu: HTMLElement;
11
+ /** Returns the menu's items. */
12
+ getItems: () => HTMLElement[];
13
+ /** Callback for menu items to register themselves with the menu. */
14
+ itemConnected(item: HTMLElement): void;
15
+ /** Callback for menu items to unregister themselves with the menu. */
16
+ itemDisconnected(item: HTMLElement): void;
17
+ }
18
+ /** Menu context to provide to menu items. */
19
+ export declare const menuContext: {
20
+ __context__: MenuContext;
21
+ };
22
+ /** Menu color configuration types. */
23
+ export type MenuColor = 'standard' | 'vibrant';
24
+ /** Menu color configurations. */
25
+ export declare const MENU_COLORS: {
26
+ readonly standard: "standard";
27
+ readonly vibrant: "vibrant";
28
+ };
29
+ /** Menu classes. */
30
+ export declare const MENU_CLASSES: {
31
+ readonly menu: "menu";
32
+ readonly menuVibrant: "menu-vibrant";
33
+ };
34
+ /** The state provided to the `menuClasses()` function. */
35
+ export interface MenuClassesState {
36
+ /** The color of the menu. */
37
+ color?: MenuColor;
38
+ }
39
+ /**
40
+ * Returns the menu classes to apply to an element based on the given state.
41
+ *
42
+ * @param state The state of the menu.
43
+ * @return An object of class names and truthy values if they apply.
44
+ */
45
+ export declare function menuClasses({ color }?: MenuClassesState): ClassInfo;
46
+ /**
47
+ * Sets up menu functionality for the given element.
48
+ *
49
+ * @param menu The element on which to set up menu functionality.
50
+ * @param opts Setup options, supports a cleanup `signal`.
51
+ */
52
+ export declare function setupMenu(menu: HTMLElement, opts?: {
53
+ signal?: AbortSignal;
54
+ }): void;
55
+ /**
56
+ * A Lit directive that adds menu styling and functionality to its element.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * html`<div class="${menu()}">TODO: add examples</div>`;
61
+ * ```
62
+ */
63
+ export declare const menu: (state?: MenuClassesState & import("../shared/directives.js").AdditionalClasses) => import("lit-html/directive.js").DirectiveResult;
64
+ /** Whether a group of menu items are single or multiple selectable. */
65
+ export type MenuItemCheckable = 'single' | 'multiple';
66
+ /** Context provided to menu items for the checkable state of a menu item group. */
67
+ export declare const menuItemCheckable: {
68
+ __context__: MenuItemCheckable;
69
+ };
70
+ /** Menu item classes. */
71
+ export declare const MENU_ITEM_CLASSES: {
72
+ readonly menuItem: "menu-item";
73
+ readonly checked: string;
74
+ readonly hover: string;
75
+ readonly focus: string;
76
+ readonly active: string;
77
+ readonly disabled: string;
78
+ };
79
+ /** The state provided to the `menuItemClasses()` function. */
80
+ export interface MenuItemClassesState {
81
+ /** Emulates `:checked`. */
82
+ checked?: boolean;
83
+ /** Emulates `:hover`. */
84
+ hover?: boolean;
85
+ /** Emulates `:focus`. */
86
+ focus?: boolean;
87
+ /** Emulates `:active`. */
88
+ active?: boolean;
89
+ /** Emulates `:disabled`. */
90
+ disabled?: boolean;
91
+ }
92
+ /**
93
+ * Returns the menu item classes to apply to an element based on the given
94
+ * state.
95
+ *
96
+ * @param state The state of the menu item.
97
+ * @return An object of class names and truthy values if they apply.
98
+ */
99
+ export declare function menuItemClasses({ checked, hover, focus, active, disabled, }?: MenuItemClassesState): ClassInfo;
100
+ /**
101
+ * Sets up menu item functionality for the given element.
102
+ *
103
+ * @param menuItem The element on which to set up menu item functionality.
104
+ * @param opts Setup options, supports a cleanup `signal`.
105
+ */
106
+ export declare function setupMenuItem(menuItem: HTMLElement, opts?: {
107
+ signal?: AbortSignal;
108
+ }): void;
109
+ /**
110
+ * A Lit directive that adds menu item styling and functionality to its element.
111
+ *
112
+ * @example
113
+ * ```ts
114
+ * html`<div class="${menuItem()}">TODO: add examples</div>`;
115
+ * ```
116
+ */
117
+ export declare const menuItem: (state?: MenuItemClassesState & import("../shared/directives.js").AdditionalClasses) => import("lit-html/directive.js").DirectiveResult;
@@ -0,0 +1,107 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { createContext } from '@lit/context';
7
+ import { FOCUS_RING_TYPES, focusRingClasses } from '../focus/focus-ring.js';
8
+ import { rippleClasses, setupRipple } from '../ripple/ripple.js';
9
+ import { createClassMapDirective } from '../shared/directives.js';
10
+ import { PSEUDO_CLASSES } from '../shared/pseudo-classes.js';
11
+ /** Menu context to provide to menu items. */
12
+ export const menuContext = createContext(Symbol('menuContext'));
13
+ /** Menu color configurations. */
14
+ export const MENU_COLORS = {
15
+ standard: 'standard',
16
+ vibrant: 'vibrant',
17
+ };
18
+ /** Menu classes. */
19
+ export const MENU_CLASSES = {
20
+ menu: 'menu',
21
+ menuVibrant: 'menu-vibrant',
22
+ };
23
+ /**
24
+ * Returns the menu classes to apply to an element based on the given state.
25
+ *
26
+ * @param state The state of the menu.
27
+ * @return An object of class names and truthy values if they apply.
28
+ */
29
+ export function menuClasses({ color } = {}) {
30
+ return {
31
+ [MENU_CLASSES.menu]: true,
32
+ [MENU_CLASSES.menuVibrant]: color === MENU_COLORS.vibrant,
33
+ };
34
+ }
35
+ /**
36
+ * Sets up menu functionality for the given element.
37
+ *
38
+ * @param menu The element on which to set up menu functionality.
39
+ * @param opts Setup options, supports a cleanup `signal`.
40
+ */
41
+ export function setupMenu(menu, opts) {
42
+ // TODO: add event listeners from <md-menu>
43
+ }
44
+ /**
45
+ * A Lit directive that adds menu styling and functionality to its element.
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * html`<div class="${menu()}">TODO: add examples</div>`;
50
+ * ```
51
+ */
52
+ export const menu = createClassMapDirective({
53
+ getClasses: menuClasses,
54
+ setupElement: setupMenu,
55
+ });
56
+ /** Context provided to menu items for the checkable state of a menu item group. */
57
+ export const menuItemCheckable = createContext(Symbol('menuItemCheckable'));
58
+ /** Menu item classes. */
59
+ export const MENU_ITEM_CLASSES = {
60
+ menuItem: 'menu-item',
61
+ checked: PSEUDO_CLASSES.checked,
62
+ hover: PSEUDO_CLASSES.hover,
63
+ focus: PSEUDO_CLASSES.focus,
64
+ active: PSEUDO_CLASSES.active,
65
+ disabled: PSEUDO_CLASSES.disabled,
66
+ };
67
+ /**
68
+ * Returns the menu item classes to apply to an element based on the given
69
+ * state.
70
+ *
71
+ * @param state The state of the menu item.
72
+ * @return An object of class names and truthy values if they apply.
73
+ */
74
+ export function menuItemClasses({ checked = false, hover = false, focus = false, active = false, disabled = false, } = {}) {
75
+ return {
76
+ ...rippleClasses(),
77
+ ...focusRingClasses({ type: FOCUS_RING_TYPES.inner }),
78
+ [MENU_ITEM_CLASSES.menuItem]: true,
79
+ [MENU_ITEM_CLASSES.checked]: checked,
80
+ [MENU_ITEM_CLASSES.hover]: hover,
81
+ [MENU_ITEM_CLASSES.focus]: focus,
82
+ [MENU_ITEM_CLASSES.active]: active,
83
+ [MENU_ITEM_CLASSES.disabled]: disabled,
84
+ };
85
+ }
86
+ /**
87
+ * Sets up menu item functionality for the given element.
88
+ *
89
+ * @param menuItem The element on which to set up menu item functionality.
90
+ * @param opts Setup options, supports a cleanup `signal`.
91
+ */
92
+ export function setupMenuItem(menuItem, opts) {
93
+ setupRipple(menuItem, opts);
94
+ }
95
+ /**
96
+ * A Lit directive that adds menu item styling and functionality to its element.
97
+ *
98
+ * @example
99
+ * ```ts
100
+ * html`<div class="${menuItem()}">TODO: add examples</div>`;
101
+ * ```
102
+ */
103
+ export const menuItem = createClassMapDirective({
104
+ getClasses: menuItemClasses,
105
+ setupElement: setupMenuItem,
106
+ });
107
+ //# sourceMappingURL=menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu.js","sourceRoot":"","sources":["menu.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAC,aAAa,EAAE,WAAW,EAAC,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAC,uBAAuB,EAAC,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAC;AAc3D,6CAA6C;AAC7C,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAc,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;AAK7E,iCAAiC;AACjC,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;CACV,CAAC;AAEX,oBAAoB;AACpB,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,cAAc;CACnB,CAAC;AAQX;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,EAAC,KAAK,KAAsB,EAAE;IACxD,OAAO;QACL,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI;QACzB,CAAC,YAAY,CAAC,WAAW,CAAC,EAAE,KAAK,KAAK,WAAW,CAAC,OAAO;KAC1D,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CACvB,IAAiB,EACjB,IAA6B;IAE7B,2CAA2C;AAC7C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,uBAAuB,CAAC;IAC1C,UAAU,EAAE,WAAW;IACvB,YAAY,EAAE,SAAS;CACxB,CAAC,CAAC;AAKH,mFAAmF;AACnF,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAC5C,MAAM,CAAC,mBAAmB,CAAC,CAC5B,CAAC;AAEF,yBAAyB;AACzB,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,EAAE,WAAW;IACrB,OAAO,EAAE,cAAc,CAAC,OAAO;IAC/B,KAAK,EAAE,cAAc,CAAC,KAAK;IAC3B,KAAK,EAAE,cAAc,CAAC,KAAK;IAC3B,MAAM,EAAE,cAAc,CAAC,MAAM;IAC7B,QAAQ,EAAE,cAAc,CAAC,QAAQ;CACzB,CAAC;AAgBX;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,OAAO,GAAG,KAAK,EACf,KAAK,GAAG,KAAK,EACb,KAAK,GAAG,KAAK,EACb,MAAM,GAAG,KAAK,EACd,QAAQ,GAAG,KAAK,MACQ,EAAE;IAC1B,OAAO;QACL,GAAG,aAAa,EAAE;QAClB,GAAG,gBAAgB,CAAC,EAAC,IAAI,EAAE,gBAAgB,CAAC,KAAK,EAAC,CAAC;QACnD,CAAC,iBAAiB,CAAC,QAAQ,CAAC,EAAE,IAAI;QAClC,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,OAAO;QACpC,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,KAAK;QAChC,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,KAAK;QAChC,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,MAAM;QAClC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,EAAE,QAAQ;KACvC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAC3B,QAAqB,EACrB,IAA6B;IAE7B,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,uBAAuB,CAAC;IAC9C,UAAU,EAAE,eAAe;IAC3B,YAAY,EAAE,aAAa;CAC5B,CAAC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {createContext} from '@lit/context';\nimport {type ClassInfo} from 'lit/directives/class-map.js';\nimport {FOCUS_RING_TYPES, focusRingClasses} from '../focus/focus-ring.js';\nimport {rippleClasses, setupRipple} from '../ripple/ripple.js';\nimport {createClassMapDirective} from '../shared/directives.js';\nimport {PSEUDO_CLASSES} from '../shared/pseudo-classes.js';\n\n/** Menu context provided to menu items. */\nexport interface MenuContext {\n /** The item's parent menu. */\n readonly menu: HTMLElement;\n /** Returns the menu's items. */\n getItems: () => HTMLElement[];\n /** Callback for menu items to register themselves with the menu. */\n itemConnected(item: HTMLElement): void;\n /** Callback for menu items to unregister themselves with the menu. */\n itemDisconnected(item: HTMLElement): void;\n}\n\n/** Menu context to provide to menu items. */\nexport const menuContext = createContext<MenuContext>(Symbol('menuContext'));\n\n/** Menu color configuration types. */\nexport type MenuColor = 'standard' | 'vibrant';\n\n/** Menu color configurations. */\nexport const MENU_COLORS = {\n standard: 'standard',\n vibrant: 'vibrant',\n} as const;\n\n/** Menu classes. */\nexport const MENU_CLASSES = {\n menu: 'menu',\n menuVibrant: 'menu-vibrant',\n} as const;\n\n/** The state provided to the `menuClasses()` function. */\nexport interface MenuClassesState {\n /** The color of the menu. */\n color?: MenuColor;\n}\n\n/**\n * Returns the menu classes to apply to an element based on the given state.\n *\n * @param state The state of the menu.\n * @return An object of class names and truthy values if they apply.\n */\nexport function menuClasses({color}: MenuClassesState = {}): ClassInfo {\n return {\n [MENU_CLASSES.menu]: true,\n [MENU_CLASSES.menuVibrant]: color === MENU_COLORS.vibrant,\n };\n}\n\n/**\n * Sets up menu functionality for the given element.\n *\n * @param menu The element on which to set up menu functionality.\n * @param opts Setup options, supports a cleanup `signal`.\n */\nexport function setupMenu(\n menu: HTMLElement,\n opts?: {signal?: AbortSignal},\n): void {\n // TODO: add event listeners from <md-menu>\n}\n\n/**\n * A Lit directive that adds menu styling and functionality to its element.\n *\n * @example\n * ```ts\n * html`<div class=\"${menu()}\">TODO: add examples</div>`;\n * ```\n */\nexport const menu = createClassMapDirective({\n getClasses: menuClasses,\n setupElement: setupMenu,\n});\n\n/** Whether a group of menu items are single or multiple selectable. */\nexport type MenuItemCheckable = 'single' | 'multiple';\n\n/** Context provided to menu items for the checkable state of a menu item group. */\nexport const menuItemCheckable = createContext<MenuItemCheckable | null>(\n Symbol('menuItemCheckable'),\n);\n\n/** Menu item classes. */\nexport const MENU_ITEM_CLASSES = {\n menuItem: 'menu-item',\n checked: PSEUDO_CLASSES.checked,\n hover: PSEUDO_CLASSES.hover,\n focus: PSEUDO_CLASSES.focus,\n active: PSEUDO_CLASSES.active,\n disabled: PSEUDO_CLASSES.disabled,\n} as const;\n\n/** The state provided to the `menuItemClasses()` function. */\nexport interface MenuItemClassesState {\n /** Emulates `:checked`. */\n checked?: boolean;\n /** Emulates `:hover`. */\n hover?: boolean;\n /** Emulates `:focus`. */\n focus?: boolean;\n /** Emulates `:active`. */\n active?: boolean;\n /** Emulates `:disabled`. */\n disabled?: boolean;\n}\n\n/**\n * Returns the menu item classes to apply to an element based on the given\n * state.\n *\n * @param state The state of the menu item.\n * @return An object of class names and truthy values if they apply.\n */\nexport function menuItemClasses({\n checked = false,\n hover = false,\n focus = false,\n active = false,\n disabled = false,\n}: MenuItemClassesState = {}): ClassInfo {\n return {\n ...rippleClasses(),\n ...focusRingClasses({type: FOCUS_RING_TYPES.inner}),\n [MENU_ITEM_CLASSES.menuItem]: true,\n [MENU_ITEM_CLASSES.checked]: checked,\n [MENU_ITEM_CLASSES.hover]: hover,\n [MENU_ITEM_CLASSES.focus]: focus,\n [MENU_ITEM_CLASSES.active]: active,\n [MENU_ITEM_CLASSES.disabled]: disabled,\n };\n}\n\n/**\n * Sets up menu item functionality for the given element.\n *\n * @param menuItem The element on which to set up menu item functionality.\n * @param opts Setup options, supports a cleanup `signal`.\n */\nexport function setupMenuItem(\n menuItem: HTMLElement,\n opts?: {signal?: AbortSignal},\n): void {\n setupRipple(menuItem, opts);\n}\n\n/**\n * A Lit directive that adds menu item styling and functionality to its element.\n *\n * @example\n * ```ts\n * html`<div class=\"${menuItem()}\">TODO: add examples</div>`;\n * ```\n */\nexport const menuItem = createClassMapDirective({\n getClasses: menuItemClasses,\n setupElement: setupMenuItem,\n});\n"]}
@@ -0,0 +1,171 @@
1
+ /*!
2
+ * Copyright 2026 Google LLC
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ // go/keep-sorted start by_regex='(.+) prefix_order=sass:
7
+ @use 'menu-tokens';
8
+ // go/keep-sorted end
9
+
10
+ @layer md.sys, md.comp.ripple, md.comp.focus-ring, md.comp.divider;
11
+ @layer md.comp.menu {
12
+ .menu {
13
+ & {
14
+ @include menu-tokens.root;
15
+ }
16
+ &.menu-vibrant {
17
+ @include menu-tokens.vibrant;
18
+ --menu-vibrant: true;
19
+ }
20
+
21
+ & {
22
+ flex-direction: column;
23
+ box-shadow: var(--container-elevation);
24
+ border-radius: var(--container-shape);
25
+ background-color: var(--container-color);
26
+ padding-block: var(--group-padding);
27
+ }
28
+
29
+ &:popover-open,
30
+ &.menu-host {
31
+ display: flex;
32
+ }
33
+
34
+ &:popover-open,
35
+ :host(:popover-open):has(&.menu-host) {
36
+ position-area: end span-end;
37
+ border: none;
38
+ }
39
+
40
+ :host(:popover-open):has(&.menu-host) {
41
+ overflow: visible;
42
+ background: none;
43
+ padding: 0;
44
+ }
45
+
46
+ &.menu-host {
47
+ overflow: auto;
48
+ }
49
+
50
+ .divider,
51
+ ::slotted(.divider) {
52
+ margin: 8px 16px;
53
+ }
54
+ }
55
+
56
+ .menu-item {
57
+ & {
58
+ @include menu-tokens.item;
59
+ }
60
+ &:first-child {
61
+ @include menu-tokens.item-first-child;
62
+ }
63
+ &:last-child {
64
+ @include menu-tokens.item-last-child;
65
+ }
66
+ @container style(--menu-vibrant: true) {
67
+ & {
68
+ @include menu-tokens.item-vibrant;
69
+ }
70
+ &:where(:hover, .hover) {
71
+ @include menu-tokens.item-vibrant-hovered;
72
+ }
73
+ &:where(:focus-within, .focus) {
74
+ @include menu-tokens.item-vibrant-focused;
75
+ }
76
+ &:where(:active, .active) {
77
+ @include menu-tokens.item-vibrant-pressed;
78
+ }
79
+ }
80
+
81
+ &:is(:checked, .checked) {
82
+ @include menu-tokens.item-selected;
83
+ @container style(--menu-vibrant: true) {
84
+ @include menu-tokens.item-selected-vibrant;
85
+ }
86
+ }
87
+
88
+ &:is(:disabled, .disabled) {
89
+ @include menu-tokens.item-disabled;
90
+ @container style(--menu-vibrant: true) {
91
+ @include menu-tokens.item-disabled-vibrant;
92
+ }
93
+ &:where(:checked, .checked) {
94
+ @include menu-tokens.item-disabled-selected;
95
+ }
96
+ }
97
+
98
+ & {
99
+ position: relative;
100
+ isolation: isolate;
101
+ display: flex;
102
+ align-items: center;
103
+ user-select: none;
104
+ box-sizing: border-box;
105
+ gap: var(--between-space);
106
+ min-height: calc(var(--height) + 4px);
107
+ border-radius: var(--shape);
108
+ padding-block: var(--top-space) var(--bottom-space);
109
+ padding-inline: var(--leading-space) var(--trailing-space);
110
+ background-image: none;
111
+ outline: none;
112
+ color: var(--label-text-color);
113
+ font: var(--label-text);
114
+ letter-spacing: var(--label-text-tracking);
115
+ }
116
+
117
+ &::before {
118
+ display: flex;
119
+ content: '';
120
+ position: absolute;
121
+ inset: 2px 4px;
122
+ z-index: -1;
123
+ border-radius: inherit;
124
+ background-color: var(--container-color);
125
+ background-image: var(--ripple);
126
+ animation: var(--ripple-animation), var(--focus-ring-animation);
127
+ transition: var(--ripple-transition);
128
+ outline: var(--focus-ring-outline);
129
+ outline-offset: var(--focus-ring-offset);
130
+ }
131
+
132
+ &:not(:disabled, .disabled) {
133
+ cursor: pointer;
134
+ }
135
+
136
+ .menu-item-content {
137
+ display: flex;
138
+ flex-direction: column;
139
+ flex: 1;
140
+ }
141
+
142
+ .menu-item-supporting-text {
143
+ color: var(--supporting-text-color);
144
+ font: var(--supporting-text);
145
+ letter-spacing: var(--supporting-text-tracking);
146
+ }
147
+
148
+ .menu-item-trailing-text {
149
+ color: var(--trailing-supporting-text-color);
150
+ font: var(--trailing-supporting-text);
151
+ letter-spacing: var(--trailing-supporting-text-tracking);
152
+ }
153
+
154
+ .menu-item-leading,
155
+ .menu-item-trailing {
156
+ display: flex;
157
+ align-items: center;
158
+ gap: 8px;
159
+ }
160
+
161
+ .menu-item-leading {
162
+ --md-icon-color: var(--leading-icon-color);
163
+ --md-icon-size: var(--leading-icon-size);
164
+ }
165
+
166
+ .menu-item-trailing {
167
+ --md-icon-color: var(--trailing-icon-color);
168
+ --md-icon-size: var(--trailing-icon-size);
169
+ }
170
+ }
171
+ }