material-inspired-component-library 1.2.2 → 2.0.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.
- package/README.md +18 -0
- package/components/badge/README.md +65 -0
- package/components/badge/index.scss +68 -0
- package/components/button/README.md +1 -1
- package/components/button/index.scss +60 -89
- package/components/button/index.ts +5 -0
- package/components/card/index.scss +29 -30
- package/components/checkbox/index.scss +1 -6
- package/components/dialog/index.scss +11 -7
- package/components/iconbutton/README.md +1 -1
- package/components/iconbutton/index.scss +46 -80
- package/components/iconbutton/index.ts +5 -0
- package/components/list/index.scss +39 -30
- package/components/list/index.ts +10 -9
- package/components/menu/README.md +67 -4
- package/components/menu/index.scss +29 -29
- package/components/menu/index.ts +47 -16
- package/components/navigationrail/README.md +150 -0
- package/components/navigationrail/index.scss +468 -0
- package/components/{checkbox → navigationrail}/index.ts +12 -7
- package/components/radio/index.scss +22 -12
- package/components/select/index.scss +5 -11
- package/components/textfield/index.scss +8 -2
- package/dist/badge.css +1 -0
- package/dist/badge.js +1 -0
- package/dist/bottomsheet.css +1 -1
- package/dist/button.css +1 -1
- package/dist/card.css +1 -1
- package/dist/checkbox.css +1 -1
- package/dist/components/menu/index.d.ts +0 -11
- package/dist/components/navigationrail/index.d.ts +5 -0
- package/dist/dialog.css +1 -1
- package/dist/iconbutton.css +1 -1
- package/dist/list.css +1 -1
- package/dist/menu.css +1 -1
- package/dist/micl.css +1 -1
- package/dist/micl.js +1 -1
- package/dist/navigationrail.css +1 -0
- package/dist/navigationrail.js +1 -0
- package/dist/radio.css +1 -1
- package/dist/select.css +1 -1
- package/dist/slider.css +1 -1
- package/dist/switch.css +1 -1
- package/dist/textfield.css +1 -1
- package/docs/button.html +5 -5
- package/docs/docs.css +2 -1
- package/docs/docs.js +2 -2
- package/docs/index.html +35 -2
- package/docs/menu.html +183 -3
- package/docs/micl.css +1 -1
- package/docs/micl.js +1 -1
- package/docs/navigationrail.html +81 -0
- package/micl.ts +20 -25
- package/package.json +10 -7
- package/styles/statelayer.scss +14 -0
- package/styles.scss +18 -1
- package/webpack.config.js +37 -0
- package/dist/components/checkbox/index.d.ts +0 -5
- package/styles/ripple.scss +0 -50
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
// SOFTWARE.
|
|
21
21
|
|
|
22
22
|
@use '../../styles/motion';
|
|
23
|
-
@use '../../styles/ripple';
|
|
24
23
|
@use '../../styles/shapes';
|
|
25
24
|
@use '../../styles/statelayer';
|
|
26
25
|
@use '../../styles/typography';
|
|
27
26
|
|
|
28
27
|
:root {
|
|
28
|
+
--md-sys-list-padding: 8px;
|
|
29
29
|
--md-sys-list-item-one-height: 56px;
|
|
30
30
|
--md-sys-list-item-two-height: 72px;
|
|
31
31
|
--md-sys-list-item-three-height: 88px;
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
--md-sys-accordion-motion-duration: #{motion.$md-sys-motion-expressive-default-spatial-duration};
|
|
44
44
|
|
|
45
45
|
margin: 0;
|
|
46
|
-
padding:
|
|
46
|
+
padding: var(--md-sys-list-padding) 0;
|
|
47
47
|
interpolate-size: allow-keywords;
|
|
48
48
|
list-style-type: none;
|
|
49
49
|
|
|
@@ -71,9 +71,6 @@
|
|
|
71
71
|
pointer-events: none;
|
|
72
72
|
}
|
|
73
73
|
&:not(.micl-list-item--disabled) {
|
|
74
|
-
@include ripple.effect;
|
|
75
|
-
--miclripple: 1;
|
|
76
|
-
|
|
77
74
|
cursor: pointer;
|
|
78
75
|
}
|
|
79
76
|
}
|
|
@@ -98,6 +95,7 @@
|
|
|
98
95
|
.micl-list-item-one,
|
|
99
96
|
.micl-list-item-two,
|
|
100
97
|
.micl-list-item-three {
|
|
98
|
+
--statelayer-color: var(--md-sys-color-on-surface);
|
|
101
99
|
--md-sys-list-item-thumbnail-aspect-ratio: 1.778;
|
|
102
100
|
|
|
103
101
|
box-sizing: border-box;
|
|
@@ -105,24 +103,39 @@
|
|
|
105
103
|
align-items: center;
|
|
106
104
|
column-gap: var(--md-sys-list-item-space);
|
|
107
105
|
padding-inline: var(--md-sys-list-item-space);
|
|
106
|
+
border: none;
|
|
108
107
|
border-radius: var(--md-sys-shape-corner-none);
|
|
109
108
|
background-color: var(--md-sys-list-item-container-color);
|
|
109
|
+
background-image:
|
|
110
|
+
radial-gradient(circle at var(--micl-x, center) var(--micl-y, center), transparent 0%, rgb(from var(--statelayer-color) r g b / var(--statelayer-opacity)) 10%, transparent 10%),
|
|
111
|
+
linear-gradient(rgb(from var(--statelayer-color) r g b / var(--statelayer-opacity)));
|
|
112
|
+
background-repeat: no-repeat;
|
|
113
|
+
background-size: 10000%, 100%;
|
|
110
114
|
list-style: none;
|
|
111
|
-
transition:
|
|
115
|
+
transition:
|
|
116
|
+
background-size 3000ms,
|
|
117
|
+
--statelayer-opacity var(--md-sys-list-motion-duration) linear;
|
|
112
118
|
|
|
119
|
+
&:not(:has(> button)) {
|
|
120
|
+
--micl-ripple: 1;
|
|
121
|
+
}
|
|
113
122
|
&> a,
|
|
123
|
+
&> button,
|
|
114
124
|
&> label {
|
|
125
|
+
box-sizing: border-box;
|
|
115
126
|
display: inherit;
|
|
116
127
|
align-items: inherit;
|
|
117
128
|
column-gap: inherit;
|
|
118
|
-
|
|
119
|
-
background-color: inherit;
|
|
129
|
+
min-height: inherit;
|
|
120
130
|
inline-size: 100%;
|
|
121
131
|
padding-inline: var(--md-sys-list-item-space);
|
|
132
|
+
border: none;
|
|
133
|
+
border-radius: inherit;
|
|
134
|
+
background-color: transparent;
|
|
122
135
|
text-decoration: none;
|
|
123
136
|
cursor: pointer;
|
|
124
137
|
}
|
|
125
|
-
&:has(> a,> label) {
|
|
138
|
+
&:has(> a,> button,> label) {
|
|
126
139
|
padding-inline: 0;
|
|
127
140
|
}
|
|
128
141
|
&:disabled,
|
|
@@ -139,14 +152,14 @@
|
|
|
139
152
|
.micl-list-item__thumbnail {
|
|
140
153
|
opacity: 38%;
|
|
141
154
|
}
|
|
142
|
-
a, label {
|
|
155
|
+
a, button, label {
|
|
143
156
|
pointer-events: none;
|
|
144
157
|
cursor: auto;
|
|
145
158
|
}
|
|
146
159
|
}
|
|
147
160
|
&:not(:disabled):not(.micl-list-item--disabled) {
|
|
148
161
|
&:hover {
|
|
149
|
-
|
|
162
|
+
--statelayer-opacity: var(--md-sys-state-hover-state-layer-opacity);
|
|
150
163
|
|
|
151
164
|
&:has(input[type=checkbox]) {
|
|
152
165
|
cursor: pointer;
|
|
@@ -156,26 +169,25 @@
|
|
|
156
169
|
}
|
|
157
170
|
}
|
|
158
171
|
&:focus-visible {
|
|
172
|
+
--statelayer-opacity: var(--md-sys-state-focus-state-layer-opacity);
|
|
173
|
+
|
|
159
174
|
outline: var(--md-sys-state-focus-indicator-thickness) solid var(--md-sys-color-secondary);
|
|
160
|
-
outline-offset:
|
|
161
|
-
background-color: color-mix(in srgb, var(--md-sys-list-item-container-color), var(--md-sys-color-on-surface) var(--md-sys-state-focus-state-layer-opacity));
|
|
175
|
+
outline-offset: var(--md-sys-state-focus-indicator-inner-offset);
|
|
162
176
|
|
|
163
177
|
.micl-list-item__icon {
|
|
164
178
|
font-variation-settings: 'FILL' 1;
|
|
165
179
|
}
|
|
166
180
|
}
|
|
167
181
|
&:active {
|
|
168
|
-
|
|
182
|
+
--statelayer-opacity: var(--md-sys-state-pressed-state-layer-opacity);
|
|
183
|
+
|
|
184
|
+
background-size: 0%, 100%;
|
|
185
|
+
transition: background-size 0ms;
|
|
169
186
|
|
|
170
187
|
.micl-list-item__icon {
|
|
171
188
|
font-variation-settings: 'FILL' 1;
|
|
172
189
|
}
|
|
173
190
|
}
|
|
174
|
-
&:has(input[type=checkbox]) {
|
|
175
|
-
@include ripple.effect;
|
|
176
|
-
--miclripple: 1;
|
|
177
|
-
--md-sys-ripple-background-color: var(--md-sys-color-primary);
|
|
178
|
-
}
|
|
179
191
|
&:has(input[type=checkbox]:checked) {
|
|
180
192
|
background-color: var(--md-sys-color-secondary-container);
|
|
181
193
|
|
|
@@ -187,18 +199,11 @@
|
|
|
187
199
|
.micl-list-item__trailing-text {
|
|
188
200
|
color: var(--md-sys-color-on-surface);
|
|
189
201
|
}
|
|
190
|
-
&:focus-visible {
|
|
191
|
-
background-color: color-mix(in srgb, var(--md-sys-color-secondary-container), var(--md-sys-color-on-surface) var(--md-sys-state-focus-state-layer-opacity));
|
|
192
|
-
}
|
|
193
|
-
&:active {
|
|
194
|
-
background-color: color-mix(in srgb, var(--md-sys-color-secondary-container), var(--md-sys-color-on-surface) var(--md-sys-state-pressed-state-layer-opacity));
|
|
195
|
-
}
|
|
196
202
|
}
|
|
197
203
|
input[type=checkbox]:not(:disabled):hover,
|
|
198
204
|
input[type=checkbox]:not(:disabled):active {
|
|
199
205
|
--checkbox-state-layer-color: initial;
|
|
200
206
|
--checkbox-outline-color: initial;
|
|
201
|
-
--md-sys-ripple-background-color: transparent;
|
|
202
207
|
}
|
|
203
208
|
}
|
|
204
209
|
}
|
|
@@ -206,7 +211,7 @@
|
|
|
206
211
|
.micl-list-item-one {
|
|
207
212
|
min-height: var(--md-sys-list-item-one-height);
|
|
208
213
|
|
|
209
|
-
&:not(:has(> a,> label)) {
|
|
214
|
+
&:not(:has(> a,> button,> label)) {
|
|
210
215
|
padding-block-start: var(--md-sys-list-item-one-padding);
|
|
211
216
|
padding-block-end: var(--md-sys-list-item-one-padding);
|
|
212
217
|
|
|
@@ -217,6 +222,7 @@
|
|
|
217
222
|
}
|
|
218
223
|
}
|
|
219
224
|
&> a,
|
|
225
|
+
&> button,
|
|
220
226
|
&> label {
|
|
221
227
|
padding-block-start: var(--md-sys-list-item-one-padding);
|
|
222
228
|
padding-block-end: var(--md-sys-list-item-one-padding);
|
|
@@ -231,7 +237,7 @@
|
|
|
231
237
|
.micl-list-item-two {
|
|
232
238
|
min-height: var(--md-sys-list-item-two-height);
|
|
233
239
|
|
|
234
|
-
&:not(:has(> a
|
|
240
|
+
&:not(:has(> a,> button,> label)) {
|
|
235
241
|
padding-block-start: var(--md-sys-list-item-two-padding);
|
|
236
242
|
padding-block-end: var(--md-sys-list-item-two-padding);
|
|
237
243
|
|
|
@@ -242,6 +248,7 @@
|
|
|
242
248
|
}
|
|
243
249
|
}
|
|
244
250
|
&> a,
|
|
251
|
+
&> button,
|
|
245
252
|
&> label {
|
|
246
253
|
padding-block-start: var(--md-sys-list-item-two-padding);
|
|
247
254
|
padding-block-end: var(--md-sys-list-item-two-padding);
|
|
@@ -261,7 +268,7 @@
|
|
|
261
268
|
.micl-list-item-three {
|
|
262
269
|
min-height: var(--md-sys-list-item-three-height);
|
|
263
270
|
|
|
264
|
-
&:not(:has(> a
|
|
271
|
+
&:not(:has(> a,> button,> label)) {
|
|
265
272
|
padding-block-start: var(--md-sys-list-item-three-padding);
|
|
266
273
|
padding-block-end: var(--md-sys-list-item-three-padding);
|
|
267
274
|
|
|
@@ -272,6 +279,7 @@
|
|
|
272
279
|
}
|
|
273
280
|
}
|
|
274
281
|
&> a,
|
|
282
|
+
&> button,
|
|
275
283
|
&> label {
|
|
276
284
|
padding-block-start: var(--md-sys-list-item-three-padding);
|
|
277
285
|
padding-block-end: var(--md-sys-list-item-three-padding);
|
|
@@ -300,9 +308,10 @@
|
|
|
300
308
|
}
|
|
301
309
|
|
|
302
310
|
.micl-list-item__icon {
|
|
303
|
-
|
|
311
|
+
min-width: 24px;
|
|
304
312
|
font-size: 24px;
|
|
305
313
|
font-variation-settings: 'FILL' 0;
|
|
314
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
306
315
|
transition: font-variation-settings var(--md-sys-list-motion-duration) linear;
|
|
307
316
|
}
|
|
308
317
|
.micl-list-item__avatar {
|
package/components/list/index.ts
CHANGED
|
@@ -58,14 +58,9 @@ export default (() =>
|
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
let
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
if (currentIndex === -1) {
|
|
66
|
-
currentIndex = 0;
|
|
67
|
-
}
|
|
68
|
-
let nextIndex = currentIndex;
|
|
61
|
+
let selectedIndex = items.findIndex(item => isSelected(item)),
|
|
62
|
+
currentIndex = items.findIndex(item => item.tabIndex === 0),
|
|
63
|
+
nextIndex = currentIndex;
|
|
69
64
|
|
|
70
65
|
switch (event.key) {
|
|
71
66
|
case 'ArrowDown':
|
|
@@ -77,7 +72,6 @@ export default (() =>
|
|
|
77
72
|
event.preventDefault();
|
|
78
73
|
break;
|
|
79
74
|
case 'Tab':
|
|
80
|
-
let selectedIndex = items.findIndex(item => isSelected(item));
|
|
81
75
|
if (selectedIndex === -1) {
|
|
82
76
|
if (currentIndex !== 0) {
|
|
83
77
|
items[currentIndex].tabIndex = -1;
|
|
@@ -102,6 +96,13 @@ export default (() =>
|
|
|
102
96
|
items[currentIndex].tabIndex = -1;
|
|
103
97
|
items[nextIndex].tabIndex = 0;
|
|
104
98
|
items[nextIndex].focus();
|
|
99
|
+
|
|
100
|
+
const btn = items[nextIndex].querySelector(':scope > button');
|
|
101
|
+
btn?.dispatchEvent(new MouseEvent('mouseenter', {
|
|
102
|
+
bubbles : true,
|
|
103
|
+
cancelable: true,
|
|
104
|
+
view : window
|
|
105
|
+
}));
|
|
105
106
|
}
|
|
106
107
|
}
|
|
107
108
|
};
|
|
@@ -4,7 +4,7 @@ This component implements the [Material Design 3 Expressive Menu](https://m3.mat
|
|
|
4
4
|
## Basic Usage
|
|
5
5
|
|
|
6
6
|
### HTML
|
|
7
|
-
The Menu component is an extension of the [List component](../list/README.md). It consists of a `<nav>` element with the `micl-menu` class, which acts as the container for a `<ul>` with the `micl-list` class. The menu can be opened and closed using a control element with the `popovertarget` attribute.
|
|
7
|
+
The Menu component is an extension of the [List component](../list/README.md). It consists of a `<nav>` element with the `micl-menu` class, which acts as the container for a `<ul>` with the `micl-list` class. The menu can be opened and closed using a control element with the `popovertarget` attribute, where the value of the attribute matches the `id` of the menu's `<nav>` element.
|
|
8
8
|
|
|
9
9
|
```HTML
|
|
10
10
|
<nav id="mymenu" class="micl-menu" popover>
|
|
@@ -17,7 +17,7 @@ The Menu component is an extension of the [List component](../list/README.md). I
|
|
|
17
17
|
</ul>
|
|
18
18
|
</nav>
|
|
19
19
|
|
|
20
|
-
<button type="button" popovertarget="mymenu">Open
|
|
20
|
+
<button type="button" popovertarget="mymenu">Open Menu</button>
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
### CSS
|
|
@@ -68,17 +68,18 @@ Since the Menu component is based on the **List component**, all of its list ite
|
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
**Example: A menu with a link**
|
|
71
|
+
|
|
71
72
|
To make a menu item function as a link, wrap its content in an `<a>` tag and set the `tabindex` to `-1`. This ensures the link is clickable but does not interfere with menu navigation.
|
|
72
73
|
|
|
73
74
|
```HTML
|
|
74
75
|
<nav id="mymenu" class="micl-menu" popover>
|
|
75
76
|
<ul class="micl-list">
|
|
76
|
-
<li class="micl-list-item-two
|
|
77
|
+
<li class="micl-list-item-two" tabindex="0">
|
|
77
78
|
<a href="https://www.nytimes.com" tabindex="-1">
|
|
78
79
|
<span class="micl-list-item__icon material-symbols-outlined" aria-hidden="true">newspaper</span>
|
|
79
80
|
<span class="micl-list-item__text">
|
|
80
81
|
<span class="micl-list-item__headline">The New York Times</span>
|
|
81
|
-
<span class="micl-list-item__supporting-text">
|
|
82
|
+
<span class="micl-list-item__supporting-text">Open the front page of The New York Times</span>
|
|
82
83
|
</span>
|
|
83
84
|
</a>
|
|
84
85
|
</li>
|
|
@@ -86,9 +87,71 @@ To make a menu item function as a link, wrap its content in an `<a>` tag and set
|
|
|
86
87
|
</nav>
|
|
87
88
|
```
|
|
88
89
|
|
|
90
|
+
**Example: A menu with a submenu**
|
|
91
|
+
|
|
92
|
+
A menu item may trigger opening a submenu when invoked by a button. Wrap the menu item content in a `<button>` tag, set its `tabindex` to `-1` and add the `popovertarget` attribute that points to the submenu. The button acts then as the control element for the submenu.
|
|
93
|
+
|
|
94
|
+
```HTML
|
|
95
|
+
<nav id="mymenu" class="micl-menu" popover>
|
|
96
|
+
<ul class="micl-list">
|
|
97
|
+
<li class="micl-list-item-one" tabindex="0">
|
|
98
|
+
<button popovertarget="mysubmenu" tabindex="-1">
|
|
99
|
+
<span class="micl-list-item__text">
|
|
100
|
+
<span class="micl-list-item__headline">Item 1</span>
|
|
101
|
+
</span>
|
|
102
|
+
<span class="micl-list-item__icon material-symbols-outlined">arrow_right</span>
|
|
103
|
+
</button>
|
|
104
|
+
<nav id="mysubmenu" class="micl-menu" popover>
|
|
105
|
+
<ul class="micl-list">
|
|
106
|
+
<li class="micl-list-item-one" tabindex="0">
|
|
107
|
+
<span class="micl-list-item__text">
|
|
108
|
+
<span class="micl-list-item__headline">Item 1-1</span>
|
|
109
|
+
</span>
|
|
110
|
+
</li>
|
|
111
|
+
<li class="micl-list-item-one" tabindex="0">
|
|
112
|
+
<span class="micl-list-item__text">
|
|
113
|
+
<span class="micl-list-item__headline">Item 1-2</span>
|
|
114
|
+
</span>
|
|
115
|
+
</li>
|
|
116
|
+
</ul>
|
|
117
|
+
</nav>
|
|
118
|
+
</li>
|
|
119
|
+
<li class="micl-list-item-one" tabindex="0">
|
|
120
|
+
<span class="micl-list-item__text">
|
|
121
|
+
<span class="micl-list-item__headline">Item 2</span>
|
|
122
|
+
</span>
|
|
123
|
+
</li>
|
|
124
|
+
</ul>
|
|
125
|
+
</nav>
|
|
126
|
+
```
|
|
127
|
+
|
|
89
128
|
Adding the `micl-list-item--disabled` class to a menu item causes the item to be displayed in a disabled state.
|
|
90
129
|
|
|
91
130
|
Add the `micl-list-item__divider` class to a menu item to create a divider between the item and the previous menu item.
|
|
92
131
|
|
|
132
|
+
## Customizations
|
|
133
|
+
You can customize the appearance of the Menu component by overriding its global CSS variables. These variables are declared on the `:root` pseudo-class and can be changed on any appropriate parent element to affect its child menus.
|
|
134
|
+
|
|
135
|
+
| Variable name | Default Value | Description |
|
|
136
|
+
| ------------- | ----- | ----------- |
|
|
137
|
+
| --md-sys-menu-width-max | 280px | The maximum width allowed for a menu |
|
|
138
|
+
| --md-sys-menu-width-min | 112px | The minimum allowed width for a menu |
|
|
139
|
+
|
|
140
|
+
**Example: Changing the maximum width**
|
|
141
|
+
|
|
142
|
+
```HTML
|
|
143
|
+
<div style="--md-sys-menu-width-max:320px">
|
|
144
|
+
<nav id="mymenu" class="micl-menu" popover>
|
|
145
|
+
<ul class="micl-list">
|
|
146
|
+
<li class="micl-list-item-one" tabindex="0">
|
|
147
|
+
<span class="micl-list-item__text">
|
|
148
|
+
<span class="micl-list-item__headline">Menu item</span>
|
|
149
|
+
</span>
|
|
150
|
+
</li>
|
|
151
|
+
</ul>
|
|
152
|
+
</nav>
|
|
153
|
+
</div>
|
|
154
|
+
```
|
|
155
|
+
|
|
93
156
|
## Compatibility
|
|
94
157
|
This component uses **popover anchor positioning** to place the menu next to its invoker. This is a modern CSS feature that may not be fully supported in all browsers. To ensure the menu works in browsers that do not support anchor positioning, wrap the menu and its invoker in a `<div>` element with `position:relative`. Please check [Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/CSS/anchor#browser_compatibility) for details.
|
|
@@ -21,23 +21,25 @@
|
|
|
21
21
|
|
|
22
22
|
@use '../../styles/elevation';
|
|
23
23
|
@use '../../styles/motion';
|
|
24
|
-
@use '../../styles/ripple';
|
|
25
24
|
@use '../../styles/shapes';
|
|
26
|
-
@use '../../styles/statelayer';
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
:root {
|
|
29
27
|
--md-sys-menu-motion-spatial: #{motion.$md-sys-motion-expressive-default-spatial};
|
|
30
28
|
--md-sys-menu-motion-duration: #{motion.$md-sys-motion-expressive-default-spatial-duration};
|
|
31
29
|
--md-sys-menu-motion-duration-reverse: #{motion.$md-sys-motion-expressive-fast-spatial-duration};
|
|
30
|
+
--md-sys-menu-width-max: 280px;
|
|
31
|
+
--md-sys-menu-width-min: 112px;
|
|
32
|
+
}
|
|
32
33
|
|
|
34
|
+
.micl-menu[popover] {
|
|
33
35
|
position: absolute;
|
|
34
36
|
inset: unset;
|
|
35
37
|
inset-block-start: anchor(end);
|
|
36
38
|
inset-inline-start: anchor(start);
|
|
37
|
-
position-try
|
|
38
|
-
min-width:
|
|
39
|
-
max-width:
|
|
40
|
-
padding
|
|
39
|
+
position-try: most-block-size flip-block, flip-inline;
|
|
40
|
+
min-width: var(--md-sys-menu-width-min);
|
|
41
|
+
max-width: var(--md-sys-menu-width-max);
|
|
42
|
+
padding: 0;
|
|
41
43
|
border: none;
|
|
42
44
|
border-radius: var(--md-sys-shape-corner-extra-small);
|
|
43
45
|
background-color: var(--md-sys-color-surface-container);
|
|
@@ -45,7 +47,7 @@
|
|
|
45
47
|
opacity: 0;
|
|
46
48
|
overflow: hidden;
|
|
47
49
|
transform: scaleY(0);
|
|
48
|
-
transform-origin: top
|
|
50
|
+
transform-origin: left top;
|
|
49
51
|
transition:
|
|
50
52
|
opacity var(--md-sys-menu-motion-duration-reverse) linear,
|
|
51
53
|
transform var(--md-sys-menu-motion-duration-reverse) var(--md-sys-menu-motion-spatial),
|
|
@@ -61,17 +63,9 @@
|
|
|
61
63
|
overlay var(--md-sys-menu-motion-duration) linear allow-discrete,
|
|
62
64
|
display var(--md-sys-menu-motion-duration) linear allow-discrete;
|
|
63
65
|
|
|
64
|
-
@position-try-on {
|
|
65
|
-
transform-origin: bottom left;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
66
|
@starting-style {
|
|
69
67
|
opacity: 0;
|
|
70
68
|
transform: scaleY(0);
|
|
71
|
-
|
|
72
|
-
@position-try-on {
|
|
73
|
-
transform-origin: bottom left;
|
|
74
|
-
}
|
|
75
69
|
}
|
|
76
70
|
&::backdrop {
|
|
77
71
|
background-color: rgba(0, 0, 0, 0.2);
|
|
@@ -89,7 +83,8 @@
|
|
|
89
83
|
display var(--md-sys-menu-motion-duration) linear allow-discrete;
|
|
90
84
|
}
|
|
91
85
|
|
|
92
|
-
.micl-list {
|
|
86
|
+
&> .micl-list {
|
|
87
|
+
--md-sys-list-padding: 4px;
|
|
93
88
|
--md-sys-list-item-one-height: 48px;
|
|
94
89
|
--md-sys-list-item-one-padding: 0;
|
|
95
90
|
--md-sys-list-item-two-padding: 0;
|
|
@@ -99,18 +94,6 @@
|
|
|
99
94
|
.micl-list-item-one,
|
|
100
95
|
.micl-list-item-two,
|
|
101
96
|
.micl-list-item-three {
|
|
102
|
-
&:not(.micl-list-item--disabled) {
|
|
103
|
-
--miclripple: 1;
|
|
104
|
-
|
|
105
|
-
@include ripple.effect;
|
|
106
|
-
|
|
107
|
-
cursor: pointer;
|
|
108
|
-
|
|
109
|
-
&:focus-visible {
|
|
110
|
-
outline-offset: calc(-1 * var(--md-sys-state-focus-indicator-thickness));
|
|
111
|
-
z-index: 1;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
97
|
&.micl-list-item__divider {
|
|
115
98
|
position: relative;
|
|
116
99
|
margin-block-start: 16px;
|
|
@@ -126,6 +109,23 @@
|
|
|
126
109
|
border-top: var(--md-sys-divider-thickness) solid var(--md-sys-divider-color);
|
|
127
110
|
}
|
|
128
111
|
}
|
|
112
|
+
&> .micl-menu[popover] {
|
|
113
|
+
transform: scaleX(0);
|
|
114
|
+
|
|
115
|
+
&:popover-open {
|
|
116
|
+
transform: scaleX(1);
|
|
117
|
+
|
|
118
|
+
@starting-style {
|
|
119
|
+
transform: scaleX(0);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
&:popover-open {
|
|
123
|
+
&::backdrop {
|
|
124
|
+
background-color: rgba(0, 0, 0, 0);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
129
128
|
}
|
|
130
129
|
}
|
|
131
130
|
}
|
|
131
|
+
|
package/components/menu/index.ts
CHANGED
|
@@ -21,27 +21,15 @@
|
|
|
21
21
|
|
|
22
22
|
export const menuSelector = '.micl-menu[popover]';
|
|
23
23
|
|
|
24
|
-
/**
|
|
25
|
-
* Set the origin for menu transformations just before transitions start.
|
|
26
|
-
* By default, the origin is "top left" (the menu opens just below the invoker, left aligned),
|
|
27
|
-
* but could also be "top right", "bottom left" or "bottom right".
|
|
28
|
-
* When the browser needs to apply a position-try-fallbacks, because there is not enough space
|
|
29
|
-
* for the menu in the default location, then the reverse transformation will be applied from
|
|
30
|
-
* the wrong origin.
|
|
31
|
-
* Therefore, when the menu is open, calculate the transformation origin just before the
|
|
32
|
-
* transitions start. When the menu is closed, do the same just after the 'display:none' has
|
|
33
|
-
* been removed by the browser (the 'toggle' event has then been triggered).
|
|
34
|
-
*/
|
|
35
24
|
export default (() =>
|
|
36
25
|
{
|
|
37
26
|
const getOrigin = (invoker: Element, popover: Element): string =>
|
|
38
27
|
{
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
oldOrigin = window.getComputedStyle(popover).getPropertyValue('transform-origin');
|
|
28
|
+
const invokerRect = invoker.getBoundingClientRect(),
|
|
29
|
+
popoverRect = popover.getBoundingClientRect();
|
|
42
30
|
|
|
43
|
-
return ((
|
|
44
|
-
((
|
|
31
|
+
return ((invokerRect.x > popoverRect.x) ? 'right ' : 'left ') +
|
|
32
|
+
((invokerRect.y > popoverRect.y) ? 'bottom' : 'top');
|
|
45
33
|
};
|
|
46
34
|
|
|
47
35
|
return {
|
|
@@ -72,6 +60,49 @@ export default (() =>
|
|
|
72
60
|
}
|
|
73
61
|
});
|
|
74
62
|
|
|
63
|
+
element.querySelectorAll<HTMLButtonElement>(
|
|
64
|
+
':scope > ul.micl-list > li > button[popovertarget]'
|
|
65
|
+
).forEach(submenuinvoker =>
|
|
66
|
+
{
|
|
67
|
+
if (submenuinvoker.popoverTargetElement?.matches('.micl-menu[popover]')) {
|
|
68
|
+
let hoverTimeout: any,
|
|
69
|
+
id = `--${submenuinvoker.popoverTargetElement.id}`;
|
|
70
|
+
|
|
71
|
+
if (submenuinvoker.popoverTargetElement instanceof HTMLElement) {
|
|
72
|
+
submenuinvoker.style.setProperty('anchor-name', id);
|
|
73
|
+
submenuinvoker.popoverTargetElement.style.insetBlockStart = `anchor(${id} start)`;
|
|
74
|
+
submenuinvoker.popoverTargetElement.style.insetInlineStart = `anchor(${id} end)`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
submenuinvoker.addEventListener('mouseenter', () =>
|
|
78
|
+
{
|
|
79
|
+
if (submenuinvoker.popoverTargetElement instanceof HTMLElement) {
|
|
80
|
+
submenuinvoker.popoverTargetElement.showPopover();
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
submenuinvoker.addEventListener('mouseleave', () =>
|
|
84
|
+
{
|
|
85
|
+
hoverTimeout = setTimeout(() => {
|
|
86
|
+
if (
|
|
87
|
+
submenuinvoker.popoverTargetElement instanceof HTMLElement
|
|
88
|
+
&& !submenuinvoker.popoverTargetElement.matches(':hover')
|
|
89
|
+
) {
|
|
90
|
+
submenuinvoker.popoverTargetElement.hidePopover();
|
|
91
|
+
}
|
|
92
|
+
}, 100);
|
|
93
|
+
});
|
|
94
|
+
submenuinvoker.popoverTargetElement.addEventListener('mouseenter', () =>
|
|
95
|
+
{
|
|
96
|
+
clearTimeout(hoverTimeout);
|
|
97
|
+
});
|
|
98
|
+
submenuinvoker.popoverTargetElement.addEventListener('mouseleave', () =>
|
|
99
|
+
{
|
|
100
|
+
if (submenuinvoker.popoverTargetElement instanceof HTMLElement) {
|
|
101
|
+
submenuinvoker.popoverTargetElement.hidePopover();
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
});
|
|
75
106
|
}
|
|
76
107
|
};
|
|
77
108
|
})();
|