material-inspired-component-library 9.1.1 → 9.1.2
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/components/appbar/index.scss +1 -1
- package/components/badge/README.md +43 -12
- package/components/badge/index.scss +15 -21
- package/components/bottomsheet/README.md +53 -22
- package/components/bottomsheet/index.scss +61 -44
- package/components/button/_shared.scss +6 -6
- package/components/card/README.md +1 -1
- package/components/checkbox/index.scss +10 -10
- package/components/datepicker/README.md +184 -59
- package/components/datepicker/index.scss +84 -20
- package/components/dialog/README.md +151 -56
- package/components/dialog/index.scss +50 -62
- package/components/iconbutton/index.scss +5 -5
- package/components/list/index.scss +6 -6
- package/components/menu/index.scss +13 -13
- package/components/navigationbar/index.scss +7 -1
- package/components/navigationrail/index.scss +27 -22
- package/components/radio/index.scss +8 -8
- package/components/select/index.scss +3 -3
- package/components/sidesheet/README.md +90 -37
- package/components/sidesheet/index.scss +51 -41
- package/components/slider/README.md +35 -9
- package/components/slider/index.scss +182 -153
- package/components/snackbar/README.md +43 -25
- package/components/snackbar/index.scss +22 -27
- package/components/stepper/index.scss +4 -4
- package/components/switch/index.scss +13 -13
- package/components/timepicker/README.md +131 -55
- package/components/timepicker/index.scss +46 -25
- package/dist/appbar.css +1 -1
- package/dist/badge.css +1 -1
- package/dist/bottomsheet.css +1 -1
- package/dist/bottomsheet.js +1 -1
- package/dist/button.css +1 -1
- package/dist/checkbox.css +1 -1
- package/dist/chip.css +1 -1
- package/dist/datepicker.css +1 -1
- package/dist/datepicker.js +1 -1
- package/dist/dialog.css +1 -1
- package/dist/iconbutton.css +1 -1
- package/dist/layout.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/navigationbar.css +1 -1
- package/dist/navigationrail.css +1 -1
- package/dist/radio.css +1 -1
- package/dist/select.css +1 -1
- package/dist/sidesheet.css +1 -1
- package/dist/slider.css +1 -1
- package/dist/slider.js +1 -1
- package/dist/snackbar.css +1 -1
- package/dist/snackbar.js +1 -1
- package/dist/stepper.css +1 -1
- package/dist/switch.css +1 -1
- package/dist/timepicker.css +1 -1
- package/dist/timepicker.js +1 -1
- package/foundations/layout/_tokens.scss +55 -0
- package/foundations/layout/index.scss +2 -35
- package/package.json +1 -1
|
@@ -139,12 +139,12 @@ $item-classes: ':is(.micl-list-item-one, .micl-list-item-two, .micl-list-item-th
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
.micl-menu[popover], select {
|
|
142
|
-
--md-comp-menu-motion-effects
|
|
143
|
-
--md-comp-menu-motion-effects-duration
|
|
144
|
-
--md-comp-menu-motion-effects-duration-reverse
|
|
145
|
-
--md-comp-menu-motion-spatial
|
|
146
|
-
--md-comp-menu-motion-spatial-duration
|
|
147
|
-
--md-comp-menu-motion-spatial-duration-reverse
|
|
142
|
+
--_menu-motion-effects: var(--md-comp-menu-motion-effects, #{motion.$md-sys-motion-expressive-fast-effects});
|
|
143
|
+
--_menu-motion-effects-duration: var(--md-comp-menu-motion-effects-duration, #{motion.$md-sys-motion-expressive-default-effects-duration});
|
|
144
|
+
--_menu-motion-effects-duration-reverse: var(--md-comp-menu-motion-effects-duration-reverse, #{motion.$md-sys-motion-expressive-default-effects-duration});
|
|
145
|
+
--_menu-motion-spatial: var(--md-comp-menu-motion-spatial, #{motion.$md-sys-motion-expressive-default-spatial});
|
|
146
|
+
--_menu-motion-spatial-duration: var(--md-comp-menu-motion-spatial-duration, #{motion.$md-sys-motion-expressive-default-spatial-duration});
|
|
147
|
+
--_menu-motion-spatial-duration-reverse: var(--md-comp-menu-motion-spatial-duration-reverse, #{motion.$md-sys-motion-expressive-fast-spatial-duration});
|
|
148
148
|
|
|
149
149
|
--md-comp-list-container-shape: var(--md-comp-menu-active-container-shape, var(--md-comp-menu-container-shape, var(--md-sys-shape-corner-large, 16px)));
|
|
150
150
|
|
|
@@ -212,7 +212,7 @@ $item-classes: ':is(.micl-list-item-one, .micl-list-item-two, .micl-list-item-th
|
|
|
212
212
|
border: none;
|
|
213
213
|
outline: none;
|
|
214
214
|
background-color: transparent;
|
|
215
|
-
--micl-duration: var(--
|
|
215
|
+
--micl-duration: var(--_menu-motion-spatial-duration-reverse);
|
|
216
216
|
--micl-easing: linear;
|
|
217
217
|
--_group-shape: var(--md-comp-menu-group-shape, var(--md-sys-shape-corner-small, 8px));
|
|
218
218
|
|
|
@@ -222,12 +222,12 @@ $item-classes: ':is(.micl-list-item-one, .micl-list-item-two, .micl-list-item-th
|
|
|
222
222
|
transform-origin: center top;
|
|
223
223
|
transition:
|
|
224
224
|
opacity var(--micl-duration) var(--micl-easing),
|
|
225
|
-
transform var(--micl-duration) var(--
|
|
225
|
+
transform var(--micl-duration) var(--_menu-motion-spatial),
|
|
226
226
|
overlay var(--micl-duration) linear allow-discrete,
|
|
227
227
|
display var(--micl-duration) linear allow-discrete;
|
|
228
228
|
|
|
229
229
|
&:popover-open {
|
|
230
|
-
--micl-duration: var(--
|
|
230
|
+
--micl-duration: var(--_menu-motion-spatial-duration);
|
|
231
231
|
--micl-easing: #{motion.$md-sys-motion-easing-emphasized-decelerate};
|
|
232
232
|
|
|
233
233
|
display: flex;
|
|
@@ -249,9 +249,9 @@ $item-classes: ':is(.micl-list-item-one, .micl-list-item-two, .micl-list-item-th
|
|
|
249
249
|
&::backdrop {
|
|
250
250
|
background-color: rgba(0, 0, 0, 0);
|
|
251
251
|
transition:
|
|
252
|
-
background-color var(--
|
|
253
|
-
overlay var(--
|
|
254
|
-
display var(--
|
|
252
|
+
background-color var(--_menu-motion-effects-duration) linear,
|
|
253
|
+
overlay var(--_menu-motion-effects-duration) linear allow-discrete,
|
|
254
|
+
display var(--_menu-motion-effects-duration) linear allow-discrete;
|
|
255
255
|
}
|
|
256
256
|
|
|
257
257
|
.micl-list {
|
|
@@ -259,7 +259,7 @@ $item-classes: ':is(.micl-list-item-one, .micl-list-item-two, .micl-list-item-th
|
|
|
259
259
|
row-gap: 2px;
|
|
260
260
|
background-color: var(--md-comp-menu-standard-container-color, var(--md-sys-color-surface-container-low));
|
|
261
261
|
box-shadow: var(--md-comp-menu-container-elevation, var(--md-sys-elevation-level2));
|
|
262
|
-
transition: border-radius var(--
|
|
262
|
+
transition: border-radius var(--_menu-motion-effects-duration-reverse) linear;
|
|
263
263
|
|
|
264
264
|
&+ .micl-list {
|
|
265
265
|
border-start-start-radius: var(--_group-shape);
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
20
|
// SOFTWARE.
|
|
21
21
|
|
|
22
|
-
@use '../../foundations/layout';
|
|
22
|
+
@use '../../foundations/layout/tokens' as layout;
|
|
23
23
|
@use '../../styles/elevation';
|
|
24
24
|
@use '../../styles/statelayer';
|
|
25
25
|
@use '../navigationrail/navitem';
|
|
@@ -115,6 +115,12 @@ nav.micl-navigationbar {
|
|
|
115
115
|
margin-block-start: 0;
|
|
116
116
|
padding-inline-end: var(--md-comp-nav-bar-item-horizontal-active-indicator-trailing-space, 16px);
|
|
117
117
|
}
|
|
118
|
+
.micl-navigationbar__text:has(+ .micl-badge--trailing) {
|
|
119
|
+
padding-inline-end: 0;
|
|
120
|
+
}
|
|
121
|
+
.micl-badge--trailing {
|
|
122
|
+
margin-inline-end: var(--md-comp-nav-bar-item-horizontal-active-indicator-trailing-space, 16px);
|
|
123
|
+
}
|
|
118
124
|
}
|
|
119
125
|
}
|
|
120
126
|
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
20
|
// SOFTWARE.
|
|
21
21
|
|
|
22
|
-
@use '../../foundations/layout';
|
|
22
|
+
@use '../../foundations/layout/tokens' as layout;
|
|
23
23
|
@use '../../styles/elevation';
|
|
24
24
|
@use '../../styles/motion';
|
|
25
25
|
@use '../../styles/shape';
|
|
@@ -44,13 +44,12 @@
|
|
|
44
44
|
@include typography.scale('label-large');
|
|
45
45
|
|
|
46
46
|
.micl-navigationrail {
|
|
47
|
-
--md-comp-nav-rail-spring-buffer
|
|
48
|
-
--md-comp-nav-rail-
|
|
49
|
-
--md-comp-nav-rail-motion-
|
|
50
|
-
--md-comp-nav-rail-motion-duration
|
|
51
|
-
--md-comp-nav-rail-
|
|
52
|
-
--md-comp-nav-rail-morph-duration
|
|
53
|
-
--md-comp-nav-rail-morph-duration-reverse: #{motion.$md-sys-motion-expressive-fast-spatial-duration};
|
|
47
|
+
--_navigationrail-spring-buffer: var(--md-comp-nav-rail-spring-buffer, 100px);
|
|
48
|
+
--_navigationrail-motion-spatial: var(--md-comp-nav-rail-motion-spatial, #{motion.$md-sys-motion-expressive-slow-spatial});
|
|
49
|
+
--_navigationrail-motion-duration: var(--md-comp-nav-rail-motion-duration, #{motion.$md-sys-motion-expressive-slow-spatial-duration});
|
|
50
|
+
--_navigationrail-motion-duration-reverse: var(--md-comp-nav-rail-motion-duration-reverse, #{motion.$md-sys-motion-expressive-default-spatial-duration});
|
|
51
|
+
--_navigationrail-morph-duration: var(--md-comp-nav-rail-morph-duration, #{motion.$md-sys-motion-expressive-fast-spatial-duration});
|
|
52
|
+
--_navigationrail-morph-duration-reverse: var(--md-comp-nav-rail-morph-duration-reverse, #{motion.$md-sys-motion-expressive-fast-spatial-duration});
|
|
54
53
|
|
|
55
54
|
--_navigationrail-current-max-width: var(--md-comp-nav-rail-collapsed-container-width, 96px);
|
|
56
55
|
--_navigationrail-current-min-width: var(--md-comp-nav-rail-collapsed-container-width, 96px);
|
|
@@ -58,10 +57,10 @@
|
|
|
58
57
|
--_navigationrail-item-width: var(--md-comp-nav-rail-item-vertical-active-indicator-width, 56px);
|
|
59
58
|
--_navigationrail-item-target-height: var(--_navigationrail-item-base-height);
|
|
60
59
|
|
|
61
|
-
--micl-duration: var(--
|
|
60
|
+
--micl-duration: var(--_navigationrail-motion-duration-reverse);
|
|
62
61
|
|
|
63
62
|
--_navigationrail-content-gap: var(--md-comp-nav-rail-item-container-vertical-space, 6px);
|
|
64
|
-
--_navigationrail-morph-speed: var(--
|
|
63
|
+
--_navigationrail-morph-speed: var(--_navigationrail-morph-duration-reverse);
|
|
65
64
|
--_navigationrail-container-delay: calc(var(--_navigationrail-morph-speed) / 2);
|
|
66
65
|
--_navigationrail-item-delay: 0ms;
|
|
67
66
|
--_navigationrail-text-animation: none;
|
|
@@ -165,7 +164,7 @@
|
|
|
165
164
|
flex-direction 0s calc(var(--_navigationrail-morph-speed) / 2) linear allow-discrete,
|
|
166
165
|
background-color calc(var(--_navigationrail-morph-speed) / 2) linear,
|
|
167
166
|
background-size 0ms,
|
|
168
|
-
--statelayer-opacity var(--
|
|
167
|
+
--statelayer-opacity var(--_navigationrail-motion-duration) linear;
|
|
169
168
|
|
|
170
169
|
.micl-navigationrail__icon {
|
|
171
170
|
@extend %micl-navitem-icon;
|
|
@@ -186,7 +185,7 @@
|
|
|
186
185
|
}
|
|
187
186
|
|
|
188
187
|
&:active {
|
|
189
|
-
transition-duration: 0ms, 0ms, 0ms, calc(var(--_navigationrail-morph-speed) / 2), 0ms, var(--
|
|
188
|
+
transition-duration: 0ms, 0ms, 0ms, calc(var(--_navigationrail-morph-speed) / 2), 0ms, var(--_navigationrail-motion-duration);
|
|
190
189
|
}
|
|
191
190
|
}
|
|
192
191
|
|
|
@@ -203,7 +202,7 @@
|
|
|
203
202
|
}
|
|
204
203
|
|
|
205
204
|
&[open] {
|
|
206
|
-
--micl-duration: var(--
|
|
205
|
+
--micl-duration: var(--_navigationrail-motion-duration);
|
|
207
206
|
|
|
208
207
|
border-start-end-radius: var(--md-comp-nav-rail-expanded-modal-container-shape, var(--md-sys-shape-corner-large));
|
|
209
208
|
border-end-end-radius: var(--md-comp-nav-rail-expanded-modal-container-shape, var(--md-sys-shape-corner-large));
|
|
@@ -237,7 +236,7 @@ nav.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggl
|
|
|
237
236
|
--_navigationrail-item-target-padding: 16px;
|
|
238
237
|
|
|
239
238
|
--_navigationrail-content-gap: 0px;
|
|
240
|
-
--_navigationrail-morph-speed: var(--
|
|
239
|
+
--_navigationrail-morph-speed: var(--_navigationrail-morph-duration);
|
|
241
240
|
--_navigationrail-container-delay: 0ms;
|
|
242
241
|
--_navigationrail-item-delay: calc(var(--_navigationrail-morph-speed) / 2);
|
|
243
242
|
--_navigationrail-text-animation: var(--_navigationrail-morph-speed) linear forwards navigationrail-text-to-expanded;
|
|
@@ -263,6 +262,12 @@ nav.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggl
|
|
|
263
262
|
margin-inline-start: var(--_navigationrail-expanded-text-margin);
|
|
264
263
|
padding-inline-end: 16px;
|
|
265
264
|
}
|
|
265
|
+
.micl-navigationrail__text:has(+ .micl-badge--trailing) {
|
|
266
|
+
padding-inline-end: 0;
|
|
267
|
+
}
|
|
268
|
+
.micl-badge--trailing {
|
|
269
|
+
margin-inline-end: 16px;
|
|
270
|
+
}
|
|
266
271
|
|
|
267
272
|
&:not(:has(.micl-navigationrail__icon)) .micl-navigationrail__text {
|
|
268
273
|
margin-inline-start: 0px;
|
|
@@ -272,7 +277,7 @@ nav.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggl
|
|
|
272
277
|
}
|
|
273
278
|
|
|
274
279
|
nav.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggle.micl-button--toggled:not([aria-pressed="true"])) {
|
|
275
|
-
--_navigationrail-morph-speed: var(--
|
|
280
|
+
--_navigationrail-morph-speed: var(--_navigationrail-morph-duration-reverse);
|
|
276
281
|
--_navigationrail-text-animation: var(--_navigationrail-morph-speed) linear forwards navigationrail-text-to-collapsed;
|
|
277
282
|
}
|
|
278
283
|
|
|
@@ -287,25 +292,25 @@ nav.micl-navigationrail {
|
|
|
287
292
|
|
|
288
293
|
dialog.micl-navigationrail {
|
|
289
294
|
display: none;
|
|
290
|
-
min-inline-size: calc(var(--md-comp-nav-rail-expanded-container-width-minimum, 220px) + var(--
|
|
291
|
-
max-inline-size: calc(var(--md-comp-nav-rail-expanded-container-width-maximum, 360px) + var(--
|
|
292
|
-
margin-inline-start: calc(-1 * (var(--md-comp-nav-rail-expanded-container-width-maximum, 360px) + var(--
|
|
293
|
-
padding-inline: var(--
|
|
295
|
+
min-inline-size: calc(var(--md-comp-nav-rail-expanded-container-width-minimum, 220px) + var(--_navigationrail-spring-buffer));
|
|
296
|
+
max-inline-size: calc(var(--md-comp-nav-rail-expanded-container-width-maximum, 360px) + var(--_navigationrail-spring-buffer));
|
|
297
|
+
margin-inline-start: calc(-1 * (var(--md-comp-nav-rail-expanded-container-width-maximum, 360px) + var(--_navigationrail-spring-buffer)));
|
|
298
|
+
padding-inline: var(--_navigationrail-spring-buffer) 0;
|
|
294
299
|
opacity: 0%;
|
|
295
300
|
|
|
296
301
|
transition:
|
|
297
302
|
opacity var(--micl-duration) linear,
|
|
298
|
-
margin-inline-start var(--micl-duration) var(--
|
|
303
|
+
margin-inline-start var(--micl-duration) var(--_navigationrail-motion-spatial),
|
|
299
304
|
overlay var(--micl-duration) linear allow-discrete,
|
|
300
305
|
display var(--micl-duration) linear allow-discrete;
|
|
301
306
|
|
|
302
307
|
&[open] {
|
|
303
308
|
display: flex;
|
|
304
|
-
margin-inline-start: calc(-1 * var(--
|
|
309
|
+
margin-inline-start: calc(-1 * var(--_navigationrail-spring-buffer));
|
|
305
310
|
opacity: 100%;
|
|
306
311
|
|
|
307
312
|
@starting-style {
|
|
308
|
-
margin-inline-start: calc(-1 * (var(--md-comp-nav-rail-expanded-container-width-maximum, 360px) + var(--
|
|
313
|
+
margin-inline-start: calc(-1 * (var(--md-comp-nav-rail-expanded-container-width-maximum, 360px) + var(--_navigationrail-spring-buffer)));
|
|
309
314
|
opacity: 0%;
|
|
310
315
|
}
|
|
311
316
|
}
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
$radio: 'input[type=radio].micl-radio';
|
|
42
42
|
|
|
43
43
|
#{$radio} {
|
|
44
|
-
--md-comp-radio-button-motion-effects
|
|
45
|
-
--md-comp-radio-button-motion-duration
|
|
46
|
-
--md-comp-radio-button-motion-duration-reverse
|
|
44
|
+
--_motion-effects: var(--md-comp-radio-button-motion-effects, #{motion.$md-sys-motion-expressive-slow-effects});
|
|
45
|
+
--_motion-duration: var(--md-comp-radio-button-motion-duration, #{motion.$md-sys-motion-expressive-slow-effects-duration});
|
|
46
|
+
--_motion-duration-reverse: var(--md-comp-radio-button-motion-duration-reverse, #{motion.$md-sys-motion-expressive-default-effects-duration});
|
|
47
47
|
|
|
48
48
|
--_size: var(--md-comp-radio-button-icon-size, 20px);
|
|
49
49
|
--_outline-width: var(--md-comp-radio-button-outline-width, 2px);
|
|
@@ -85,8 +85,8 @@ $radio: 'input[type=radio].micl-radio';
|
|
|
85
85
|
background-clip: content-box;
|
|
86
86
|
border-radius: var(--md-sys-shape-corner-full);
|
|
87
87
|
transition:
|
|
88
|
-
padding var(--
|
|
89
|
-
border-color var(--
|
|
88
|
+
padding var(--_motion-duration-reverse) var(--_motion-effects),
|
|
89
|
+
border-color var(--_motion-duration-reverse) motion.$md-sys-motion-easing-emphasized;
|
|
90
90
|
}
|
|
91
91
|
&:checked {
|
|
92
92
|
--statelayer-color: var(--md-sys-color-primary);
|
|
@@ -96,8 +96,8 @@ $radio: 'input[type=radio].micl-radio';
|
|
|
96
96
|
|
|
97
97
|
padding: calc((var(--_size) / 4) - var(--_outline-width));
|
|
98
98
|
transition:
|
|
99
|
-
padding var(--
|
|
100
|
-
border-color var(--
|
|
99
|
+
padding var(--_motion-duration) var(--_motion-effects),
|
|
100
|
+
border-color var(--_motion-duration) motion.$md-sys-motion-easing-emphasized;
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
&:not(:disabled) {
|
|
@@ -117,7 +117,7 @@ $radio: 'input[type=radio].micl-radio';
|
|
|
117
117
|
cursor: pointer;
|
|
118
118
|
transition:
|
|
119
119
|
background-size 0ms,
|
|
120
|
-
--statelayer-opacity var(--
|
|
120
|
+
--statelayer-opacity var(--_motion-duration) linear;
|
|
121
121
|
|
|
122
122
|
&:hover {
|
|
123
123
|
--statelayer-opacity: var(--md-sys-state-hover-state-layer-opacity, 8%);
|
|
@@ -41,8 +41,8 @@ $selects: ':is(.micl-textfield-filled, .micl-textfield-outlined) > select';
|
|
|
41
41
|
--_line-height: var(--md-comp-text-field-container-height, 56px);
|
|
42
42
|
}
|
|
43
43
|
#{$selects} {
|
|
44
|
-
--md-comp-list-motion-effects
|
|
45
|
-
--md-comp-list-motion-duration
|
|
44
|
+
--_list-motion-effects: var(--md-comp-list-motion-effects, #{motion.$md-sys-motion-expressive-fast-spatial});
|
|
45
|
+
--_list-motion-duration: var(--md-comp-list-motion-duration, #{motion.$md-sys-motion-expressive-default-effects-duration});
|
|
46
46
|
|
|
47
47
|
appearance: base-select;
|
|
48
48
|
line-height: var(--_line-height);
|
|
@@ -168,7 +168,7 @@ $selects: ':is(.micl-textfield-filled, .micl-textfield-outlined) > select';
|
|
|
168
168
|
// the list transition is repeated here without it.
|
|
169
169
|
transition:
|
|
170
170
|
background-size 0ms,
|
|
171
|
-
--statelayer-opacity var(--
|
|
171
|
+
--statelayer-opacity var(--_list-motion-duration) linear;
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Side sheet
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
This component implements the [Material Design 3 Expressive Side sheet](https://m3.material.io/components/side-sheets/overview) specification. Side sheets display optional content and actions without interrupting the user's workflow in the main content area.
|
|
3
4
|
|
|
4
5
|
## Basic Usage
|
|
5
6
|
|
|
@@ -14,6 +15,7 @@ To create a standard side sheet, use the `<dialog>` element with the `popover` a
|
|
|
14
15
|
type="button"
|
|
15
16
|
class="micl-iconbutton-standard-s material-symbols-outlined"
|
|
16
17
|
popovertarget="mysidesheet"
|
|
18
|
+
aria-label="Close"
|
|
17
19
|
>close</button>
|
|
18
20
|
</div>
|
|
19
21
|
<div class="micl-sidesheet__content">
|
|
@@ -32,7 +34,7 @@ Import the side sheet styles into your project:
|
|
|
32
34
|
@use "material-inspired-component-library/dist/sidesheet";
|
|
33
35
|
```
|
|
34
36
|
|
|
35
|
-
|
|
37
|
+
Alternatively, import all MICL styles at once:
|
|
36
38
|
```CSS
|
|
37
39
|
@use "material-inspired-component-library/styles";
|
|
38
40
|
```
|
|
@@ -41,25 +43,67 @@ Or import all MICL styles:
|
|
|
41
43
|
No custom JavaScript is required for the core functionality of the side sheet component.
|
|
42
44
|
|
|
43
45
|
### Live Demo
|
|
44
|
-
A live
|
|
46
|
+
A live interactive demo of the [Side sheet component](https://henkpb.github.io/micl/sidesheet.html) is available.
|
|
47
|
+
|
|
48
|
+
## Anatomy
|
|
49
|
+
A **standard** side sheet allows the rest of the page to remain usable by dynamically narrowing the main content area to make room for itself. Its headline and actions container are both optional; a side sheet may consist of nothing but content.
|
|
50
|
+
|
|
51
|
+
| Element | Meaning |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| `dialog.micl-sidesheet` | The container. Add the `popover` attribute for a standard side sheet; omit it for a modal one. |
|
|
54
|
+
| `.micl-sidesheet__headline` | The header row: holds an optional back button, a heading, and an optional close button. |
|
|
55
|
+
| `.micl-sidesheet__content` | The scrollable body of the side sheet. |
|
|
56
|
+
| `.micl-sidesheet__actions` | An optional row of buttons pinned to the bottom, usually preceded by an `<hr class="micl-divider">`. |
|
|
57
|
+
|
|
58
|
+
A side sheet is **docked**, meaning it spans the full height of the viewport and sits flush against the trailing edge.
|
|
59
|
+
|
|
60
|
+
> [!WARNING]
|
|
61
|
+
> The **standard** side sheet component dynamically applies CSS rules to the `<body>` element to properly resize the main content area when the sheet is open. Overriding these rules may cause unexpected layout behavior. The applied rules are:
|
|
62
|
+
> ```CSS
|
|
63
|
+
> box-sizing: border-box;
|
|
64
|
+
> margin: 0;
|
|
65
|
+
> max-inline-size: /* varies dynamically based on side sheet state */
|
|
66
|
+
> transition: /* handles max-inline-size animation */
|
|
67
|
+
> ```
|
|
68
|
+
>
|
|
69
|
+
> These rules only take effect on medium window size classes (600px) and wider. On compact screens lacking horizontal space, the main content area is left untouched and the side sheet simply overlays it.
|
|
45
70
|
|
|
46
71
|
## Variants
|
|
47
|
-
|
|
72
|
+
Using a plain `popover` attribute makes the side sheet an *auto* popover: it closes automatically when the user presses <kbd>Esc</kbd> or clicks anywhere outside of it. This behavior is ideal for temporary panels like settings menus.
|
|
48
73
|
|
|
49
|
-
|
|
74
|
+
### Co-Existing Side Sheet
|
|
75
|
+
For a side sheet that should remain open while the user interacts with the main content, use `popover="manual"` instead. A manual popover is only dismissed by its own close button:
|
|
50
76
|
|
|
77
|
+
```HTML
|
|
78
|
+
<dialog id="mysidesheet" class="micl-sidesheet" popover="manual" aria-labelledby="mytitle">
|
|
79
|
+
...
|
|
80
|
+
</dialog>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
To open a **standard** side sheet, link a trigger button to the sheet's ID using `popovertarget`:
|
|
84
|
+
```HTML
|
|
85
|
+
<button type="button" popovertarget="mysidesheet">Open Side Sheet</button>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Modal Side Sheet
|
|
89
|
+
A **modal** side sheet blocks access to the rest of the page and requires the user to explicitly dismiss it. This variant is suitable for critical tasks or information requiring full attention.
|
|
90
|
+
|
|
91
|
+
To create a modal side sheet, use the `<dialog>` element *without* the `popover` attribute. Because it isn't a popover, `popovertarget` has no effect. Instead, you must provide a button (or another control) using `command="close"` to dismiss it. A modal side sheet is inherently not dismissed by outside clicks; explicitly setting `closedby="closerequest"` enforces this behavior while keeping the <kbd>Esc</kbd> key functional. (If you *do* want outside clicks to close it, use `closedby="any"` instead).
|
|
51
92
|
```HTML
|
|
52
93
|
<dialog id="mysidesheet" class="micl-sidesheet" closedby="closerequest" aria-labelledby="mytitle">
|
|
53
94
|
<div class="micl-sidesheet__headline">
|
|
54
95
|
<button
|
|
55
96
|
type="button"
|
|
56
97
|
class="micl-iconbutton-standard-s material-symbols-outlined"
|
|
98
|
+
aria-label="Back"
|
|
57
99
|
>arrow_back</button>
|
|
58
100
|
<h2 id="mytitle">Title</h2>
|
|
59
101
|
<button
|
|
60
102
|
type="button"
|
|
61
103
|
class="micl-iconbutton-standard-s material-symbols-outlined"
|
|
62
|
-
|
|
104
|
+
command="close"
|
|
105
|
+
commandfor="mysidesheet"
|
|
106
|
+
aria-label="Close"
|
|
63
107
|
>close</button>
|
|
64
108
|
</div>
|
|
65
109
|
<div class="micl-sidesheet__content">
|
|
@@ -72,54 +116,63 @@ To create a modal side sheet, use the `<dialog>` element without the `popover` a
|
|
|
72
116
|
</dialog>
|
|
73
117
|
```
|
|
74
118
|
|
|
75
|
-
To open a
|
|
119
|
+
To open a **modal** side sheet, use the `show-modal` command instead:
|
|
76
120
|
```HTML
|
|
77
|
-
<button type="button"
|
|
121
|
+
<button type="button" command="show-modal" commandfor="mysidesheet">Open Side Sheet</button>
|
|
78
122
|
```
|
|
79
123
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
> [!WARNING]
|
|
88
|
-
> The **standard** side sheet component adds CSS rules to the `<body>` element to properly resize the main content area when the side sheet is open. Overriding these rules may cause the component to behave unexpectedly. The rules that are applied are:
|
|
89
|
-
> ```CSS
|
|
90
|
-
> box-sizing: border-box;
|
|
91
|
-
> margin: 0;
|
|
92
|
-
> max-inline-size: ...varies depending on if the side sheet is opened...
|
|
93
|
-
> transition: ...transition on max-inline-size...
|
|
94
|
-
> ```
|
|
124
|
+
## Accessibility
|
|
125
|
+
* **Name the side sheet:** A `<dialog>` is exposed to assistive technologies as a dialog. Always provide an accessible name by pointing `aria-labelledby` to the headline's heading `id`.
|
|
126
|
+
* **Name the icon buttons:** Always provide a descriptive `aria-label` for icon buttons, like the back and close buttons.
|
|
127
|
+
* **Manage initial focus:** A standard side sheet relies on the Popover API, which automatically moves focus into the side sheet when the user tabs away from the trigger button, and returns focus upon closing. A modal side sheet natively focuses its first focusable descendant. This is rarely the desired behavior if the first element is a "Back" button. Add the `autofocus` attribute to the control that should legitimately receive focus first. *(Note: placing `autofocus` directly on the `<dialog>` element is ignored).*
|
|
128
|
+
* **Scrolling by keyboard:** When the content container overflows, modern browsers make it a distinct tab stop (often with a visible focus ring) so it can be scrolled via arrow keys. This is a deliberate accessibility feature; do not suppress the focus ring.
|
|
129
|
+
* **Dismissal constraints:** A side sheet opened with `popover` or `showModal()` is dismissed via the <kbd>Esc</kbd> key. A `popover="manual"` side sheet is not, meaning a visible close button is strictly required.
|
|
130
|
+
* **Respect motion preferences:** All motion is automatically disabled if the user has requested reduced motion at the OS level. The side sheet (and the main content resizing) will toggle instantly.
|
|
95
131
|
|
|
96
132
|
## Theming
|
|
97
|
-
Each side sheet
|
|
133
|
+
Each side sheet can be themed using CSS custom properties formatted to match the Material Design 3 component-token naming convention.
|
|
98
134
|
|
|
99
135
|
| Custom property | Meaning | Default |
|
|
100
|
-
|
|
101
|
-
| `--md-comp-sidesheet-container-width` | The
|
|
102
|
-
| `--md-comp-sidesheet-container-max-width` | The
|
|
103
|
-
| `--md-comp-sidesheet-padding` | The
|
|
136
|
+
| --- | --- | --- |
|
|
137
|
+
| `--md-comp-sidesheet-container-width` | The width of the side sheet | `256px` |
|
|
138
|
+
| `--md-comp-sidesheet-container-max-width` | The maximum allowed width of the side sheet; any larger `--md-comp-sidesheet-container-width` is clamped to this | `400px` |
|
|
139
|
+
| `--md-comp-sidesheet-padding` | The padding between the vertical edges and the content | `--md-sys-layout-window-margin` |
|
|
140
|
+
| `--md-comp-sidesheet-headline-height` | The minimum height of the headline row; increase this if using icon buttons larger than `micl-iconbutton-standard-s` | `40px` |
|
|
104
141
|
| `--md-comp-sidesheet-container-shape` | The corner rounding of the standard side sheet | `--md-sys-shape-corner-none` |
|
|
142
|
+
| `--md-comp-sidesheet-content-color` | The text color inside the side sheet | `--md-sys-color-on-surface` |
|
|
105
143
|
| `--md-comp-sidesheet-standard-container-color` | The background color of the standard side sheet | `--md-sys-color-surface` |
|
|
106
|
-
| `--md-comp-sidesheet-divider-thickness` | The thickness of the
|
|
107
|
-
| `--md-comp-sidesheet-divider-color` | The color of the
|
|
108
|
-
| `--md-comp-sidesheet-standard-container-elevation` | The shadow (elevation) of the standard side sheet | `--md-sys-elevation-level0` |
|
|
144
|
+
| `--md-comp-sidesheet-divider-thickness` | The thickness of the standard side sheet's vertical divider | `1px` |
|
|
145
|
+
| `--md-comp-sidesheet-divider-color` | The color of the standard side sheet's vertical divider | `--md-sys-color-outline-variant` |
|
|
146
|
+
| `--md-comp-sidesheet-standard-container-elevation` | The shadow depth (elevation) of the standard side sheet | `--md-sys-elevation-level0` |
|
|
109
147
|
| `--md-comp-sidesheet-modal-container-color` | The background color of the modal side sheet | `--md-sys-color-surface-container-low` |
|
|
110
|
-
| `--md-comp-sidesheet-modal-container-elevation` | The shadow (elevation) of the modal side sheet | `--md-sys-elevation-level1` |
|
|
111
|
-
| `--md-comp-sidesheet-modal-container-shape` | The corner rounding of the modal side sheet
|
|
148
|
+
| `--md-comp-sidesheet-modal-container-elevation` | The shadow depth (elevation) of the modal side sheet | `--md-sys-elevation-level1` |
|
|
149
|
+
| `--md-comp-sidesheet-modal-container-shape` | The corner rounding of the modal side sheet (applied to the two corners facing the main content) | `--md-sys-shape-corner-large` |
|
|
150
|
+
| `--md-comp-sidesheet-motion-spatial` | The easing function for sliding the side sheet (uses a spring animation that slightly overshoots before settling) | `--md-sys-motion-expressive-slow-spatial` |
|
|
151
|
+
| `--md-comp-sidesheet-motion-duration` | Animation duration for opening | `650ms` |
|
|
152
|
+
| `--md-comp-sidesheet-motion-duration-reverse` | Animation duration for closing | `500ms` |
|
|
112
153
|
|
|
113
|
-
|
|
114
|
-
**Example: Changing the width of the sidesheet**
|
|
154
|
+
**Example: Changing the width of the side sheet**
|
|
115
155
|
|
|
116
156
|
```HTML
|
|
117
|
-
<body style="--md-comp-sidesheet-container-width:320px">
|
|
157
|
+
<body style="--md-comp-sidesheet-container-width: 320px;">
|
|
118
158
|
<dialog id="mysidesheet" class="micl-sidesheet" popover>
|
|
119
159
|
...
|
|
120
160
|
</dialog>
|
|
121
161
|
</body>
|
|
122
162
|
```
|
|
123
163
|
|
|
164
|
+
To remove the vertical divider of a standard side sheet, set the following CSS variable to zero:
|
|
165
|
+
```CSS
|
|
166
|
+
#mysidesheet {
|
|
167
|
+
--md-comp-sidesheet-divider-thickness: 0;
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
> [!NOTE]
|
|
172
|
+
> For a **standard** side sheet, define the `--md-comp-sidesheet-container-width` custom property on the `<body>` (or `:root`) element rather than on the side sheet itself. The CSS rule responsible for shrinking the main content area reads this variable from the body. Setting it only on the `<dialog>` would cause the side sheet and the main content area to fall out of sync.
|
|
173
|
+
|
|
124
174
|
## Compatibility
|
|
125
|
-
|
|
175
|
+
|
|
176
|
+
The standard side sheet relies on the Popover API. Please review [browser compatibility for the Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API) if you are targeting older browsers.
|
|
177
|
+
|
|
178
|
+
The modal side sheet is opened and closed using the `command` and `commandfor` attributes. Review [browser compatibility for the Invoker Commands API](https://developer.mozilla.org/en-US/docs/Web/API/Invoker_Commands_API). If these attributes are not supported in your target environments, calling `showModal()` and `close()` via JavaScript serves as an effective fallback.
|