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.
Files changed (61) hide show
  1. package/components/appbar/index.scss +1 -1
  2. package/components/badge/README.md +43 -12
  3. package/components/badge/index.scss +15 -21
  4. package/components/bottomsheet/README.md +53 -22
  5. package/components/bottomsheet/index.scss +61 -44
  6. package/components/button/_shared.scss +6 -6
  7. package/components/card/README.md +1 -1
  8. package/components/checkbox/index.scss +10 -10
  9. package/components/datepicker/README.md +184 -59
  10. package/components/datepicker/index.scss +84 -20
  11. package/components/dialog/README.md +151 -56
  12. package/components/dialog/index.scss +50 -62
  13. package/components/iconbutton/index.scss +5 -5
  14. package/components/list/index.scss +6 -6
  15. package/components/menu/index.scss +13 -13
  16. package/components/navigationbar/index.scss +7 -1
  17. package/components/navigationrail/index.scss +27 -22
  18. package/components/radio/index.scss +8 -8
  19. package/components/select/index.scss +3 -3
  20. package/components/sidesheet/README.md +90 -37
  21. package/components/sidesheet/index.scss +51 -41
  22. package/components/slider/README.md +35 -9
  23. package/components/slider/index.scss +182 -153
  24. package/components/snackbar/README.md +43 -25
  25. package/components/snackbar/index.scss +22 -27
  26. package/components/stepper/index.scss +4 -4
  27. package/components/switch/index.scss +13 -13
  28. package/components/timepicker/README.md +131 -55
  29. package/components/timepicker/index.scss +46 -25
  30. package/dist/appbar.css +1 -1
  31. package/dist/badge.css +1 -1
  32. package/dist/bottomsheet.css +1 -1
  33. package/dist/bottomsheet.js +1 -1
  34. package/dist/button.css +1 -1
  35. package/dist/checkbox.css +1 -1
  36. package/dist/chip.css +1 -1
  37. package/dist/datepicker.css +1 -1
  38. package/dist/datepicker.js +1 -1
  39. package/dist/dialog.css +1 -1
  40. package/dist/iconbutton.css +1 -1
  41. package/dist/layout.css +1 -1
  42. package/dist/list.css +1 -1
  43. package/dist/menu.css +1 -1
  44. package/dist/micl.css +1 -1
  45. package/dist/micl.js +1 -1
  46. package/dist/navigationbar.css +1 -1
  47. package/dist/navigationrail.css +1 -1
  48. package/dist/radio.css +1 -1
  49. package/dist/select.css +1 -1
  50. package/dist/sidesheet.css +1 -1
  51. package/dist/slider.css +1 -1
  52. package/dist/slider.js +1 -1
  53. package/dist/snackbar.css +1 -1
  54. package/dist/snackbar.js +1 -1
  55. package/dist/stepper.css +1 -1
  56. package/dist/switch.css +1 -1
  57. package/dist/timepicker.css +1 -1
  58. package/dist/timepicker.js +1 -1
  59. package/foundations/layout/_tokens.scss +55 -0
  60. package/foundations/layout/index.scss +2 -35
  61. 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: #{motion.$md-sys-motion-expressive-fast-effects};
143
- --md-comp-menu-motion-effects-duration: #{motion.$md-sys-motion-expressive-default-effects-duration};
144
- --md-comp-menu-motion-effects-duration-reverse: #{motion.$md-sys-motion-expressive-default-effects-duration};
145
- --md-comp-menu-motion-spatial: #{motion.$md-sys-motion-expressive-default-spatial};
146
- --md-comp-menu-motion-spatial-duration: #{motion.$md-sys-motion-expressive-default-spatial-duration};
147
- --md-comp-menu-motion-spatial-duration-reverse: #{motion.$md-sys-motion-expressive-fast-spatial-duration};
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(--md-comp-menu-motion-spatial-duration-reverse);
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(--md-comp-menu-motion-spatial),
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(--md-comp-menu-motion-spatial-duration);
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(--md-comp-menu-motion-effects-duration) linear,
253
- overlay var(--md-comp-menu-motion-effects-duration) linear allow-discrete,
254
- display var(--md-comp-menu-motion-effects-duration) linear allow-discrete;
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(--md-comp-menu-motion-effects-duration-reverse) linear;
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: 100px;
48
- --md-comp-nav-rail-divider-thickness: 0px;
49
- --md-comp-nav-rail-motion-spatial: #{motion.$md-sys-motion-expressive-slow-spatial};
50
- --md-comp-nav-rail-motion-duration: #{motion.$md-sys-motion-expressive-slow-spatial-duration};
51
- --md-comp-nav-rail-motion-duration-reverse: #{motion.$md-sys-motion-expressive-default-spatial-duration};
52
- --md-comp-nav-rail-morph-duration: #{motion.$md-sys-motion-expressive-fast-spatial-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(--md-comp-nav-rail-motion-duration-reverse);
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(--md-comp-nav-rail-morph-duration-reverse);
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(--md-comp-nav-rail-motion-duration) linear;
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(--md-comp-nav-rail-motion-duration);
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(--md-comp-nav-rail-motion-duration);
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(--md-comp-nav-rail-morph-duration);
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(--md-comp-nav-rail-morph-duration-reverse);
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(--md-comp-nav-rail-spring-buffer));
291
- max-inline-size: calc(var(--md-comp-nav-rail-expanded-container-width-maximum, 360px) + var(--md-comp-nav-rail-spring-buffer));
292
- margin-inline-start: calc(-1 * (var(--md-comp-nav-rail-expanded-container-width-maximum, 360px) + var(--md-comp-nav-rail-spring-buffer)));
293
- padding-inline: var(--md-comp-nav-rail-spring-buffer) 0;
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(--md-comp-nav-rail-motion-spatial),
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(--md-comp-nav-rail-spring-buffer));
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(--md-comp-nav-rail-spring-buffer)));
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: #{motion.$md-sys-motion-expressive-slow-effects};
45
- --md-comp-radio-button-motion-duration: #{motion.$md-sys-motion-expressive-slow-effects-duration};
46
- --md-comp-radio-button-motion-duration-reverse: #{motion.$md-sys-motion-expressive-default-effects-duration};
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(--md-comp-radio-button-motion-duration-reverse) var(--md-comp-radio-button-motion-effects),
89
- border-color var(--md-comp-radio-button-motion-duration-reverse) motion.$md-sys-motion-easing-emphasized;
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(--md-comp-radio-button-motion-duration) var(--md-comp-radio-button-motion-effects),
100
- border-color var(--md-comp-radio-button-motion-duration) motion.$md-sys-motion-easing-emphasized;
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(--md-comp-radio-button-motion-duration) linear;
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: #{motion.$md-sys-motion-expressive-fast-spatial};
45
- --md-comp-list-motion-duration: #{motion.$md-sys-motion-expressive-default-effects-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(--md-comp-list-motion-duration) linear;
171
+ --statelayer-opacity var(--_list-motion-duration) linear;
172
172
  }
173
173
  }
174
174
  }
@@ -1,5 +1,6 @@
1
1
  # Side sheet
2
- This component implements the [Material Design 3 Expressive Side sheet](https://m3.material.io/components/side-sheets/overview) design. Side sheets provide optional content and actions without interrupting the main content.
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
- Or import all MICL styles:
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 example of the [Side sheet component](https://henkpb.github.io/micl/sidesheet.html) is available to interact with.
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
- A **modal** side sheet blocks access to the rest of the page and must be dismissed explicitly by the user. This is suitable for critical tasks or information that requires a user's full attention.
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
- To create a modal side sheet, use the `<dialog>` element without the `popover` attribute. Use `closedby="closerequest"` to prevent the side sheet from being dismissed by clicking outside of it. You'll also need a button or other control with `popovertarget` to close it.
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
- popovertarget="mysidesheet"
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 standard or modal side sheet, link a button to the side sheet's ID using the `popovertarget` attribute:
119
+ To open a **modal** side sheet, use the `show-modal` command instead:
76
120
  ```HTML
77
- <button type="button" popovertarget="mysidesheet">Open Side Sheet</button>
121
+ <button type="button" command="show-modal" commandfor="mysidesheet">Open Side Sheet</button>
78
122
  ```
79
123
 
80
- The back-button and the actions-container are optional. To remove the vertical divider of the standard side sheet, assign zero to the following CSS variable:
81
- ```CSS
82
- #mysidesheet {
83
- --md-comp-sidesheet-divider-thickness: 0;
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 style can be themed with CSS custom properties that follow the Material Design 3 component-token naming convention.
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 default (and minimum allowed) width of the side sheet | `256px` |
102
- | `--md-comp-sidesheet-container-max-width` | The largest allowed width of the side sheet | `400px` |
103
- | `--md-comp-sidesheet-padding` | The amount of space between the vertical edges and the content | `--md-sys-layout-window-margin` |
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 vertical divider of the standard side sheet | `1px` |
107
- | `--md-comp-sidesheet-divider-color` | The color of the vertical divider of the standard side sheet | `--md-sys-color-outline` |
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, applied to the two corners facing the content | `--md-sys-shape-corner-large` |
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
- This component uses the Popover API, which might not be supported in all browsers. Please check [Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API#api.htmlelement.popover) for details.
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.