material-inspired-component-library 9.1.0 → 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 (73) hide show
  1. package/README.md +2 -1
  2. package/components/appbar/index.scss +1 -1
  3. package/components/badge/README.md +43 -12
  4. package/components/badge/index.scss +15 -21
  5. package/components/bottomsheet/README.md +53 -22
  6. package/components/bottomsheet/index.scss +62 -45
  7. package/components/button/_shared.scss +9 -9
  8. package/components/card/README.md +55 -25
  9. package/components/card/index.scss +57 -38
  10. package/components/checkbox/README.md +97 -28
  11. package/components/checkbox/index.scss +39 -29
  12. package/components/chip/index.scss +6 -6
  13. package/components/datepicker/README.md +184 -59
  14. package/components/datepicker/index.scss +85 -21
  15. package/components/dialog/README.md +151 -56
  16. package/components/dialog/index.scss +50 -62
  17. package/components/iconbutton/index.scss +8 -8
  18. package/components/list/index.scss +15 -11
  19. package/components/menu/index.scss +13 -13
  20. package/components/navigationbar/index.scss +7 -1
  21. package/components/navigationrail/index.scss +27 -22
  22. package/components/radio/README.md +52 -12
  23. package/components/radio/index.scss +59 -41
  24. package/components/select/index.scss +3 -3
  25. package/components/sidesheet/README.md +90 -37
  26. package/components/sidesheet/index.scss +51 -41
  27. package/components/slider/README.md +35 -9
  28. package/components/slider/index.scss +182 -153
  29. package/components/snackbar/README.md +43 -25
  30. package/components/snackbar/index.scss +22 -27
  31. package/components/stepper/index.scss +5 -5
  32. package/components/switch/README.md +32 -4
  33. package/components/switch/index.scss +57 -52
  34. package/components/timepicker/README.md +131 -55
  35. package/components/timepicker/index.scss +47 -26
  36. package/dist/appbar.css +1 -1
  37. package/dist/badge.css +1 -1
  38. package/dist/bottomsheet.css +1 -1
  39. package/dist/bottomsheet.js +1 -1
  40. package/dist/button.css +1 -1
  41. package/dist/card.css +1 -1
  42. package/dist/checkbox.css +1 -1
  43. package/dist/checkbox.js +1 -1
  44. package/dist/chip.css +1 -1
  45. package/dist/components/checkbox/index.d.ts +1 -0
  46. package/dist/datepicker.css +1 -1
  47. package/dist/datepicker.js +1 -1
  48. package/dist/dialog.css +1 -1
  49. package/dist/foundations/form/index.js +1 -1
  50. package/dist/iconbutton.css +1 -1
  51. package/dist/layout.css +1 -1
  52. package/dist/list.css +1 -1
  53. package/dist/menu.css +1 -1
  54. package/dist/micl.css +1 -1
  55. package/dist/micl.js +1 -1
  56. package/dist/navigationbar.css +1 -1
  57. package/dist/navigationrail.css +1 -1
  58. package/dist/radio.css +1 -1
  59. package/dist/select.css +1 -1
  60. package/dist/sidesheet.css +1 -1
  61. package/dist/slider.css +1 -1
  62. package/dist/slider.js +1 -1
  63. package/dist/snackbar.css +1 -1
  64. package/dist/snackbar.js +1 -1
  65. package/dist/stepper.css +1 -1
  66. package/dist/stepper.js +1 -1
  67. package/dist/switch.css +1 -1
  68. package/dist/timepicker.css +1 -1
  69. package/dist/timepicker.js +1 -1
  70. package/foundations/layout/_tokens.scss +55 -0
  71. package/foundations/layout/index.scss +5 -35
  72. package/package.json +2 -2
  73. package/{components/checkbox/_label.scss → styles/togglelabel.scss} +11 -3
@@ -19,6 +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/tokens' as layout;
22
23
  @use '../../styles/elevation';
23
24
  @use '../../styles/motion';
24
25
  @use '../../styles/shape';
@@ -32,31 +33,25 @@
32
33
  @include shape.corner('none');
33
34
  @include shape.corner('extra-large');
34
35
 
35
- @include statelayer.token('hover-state-layer-opacity');
36
36
  @include statelayer.token('backdrop-opacity');
37
- @include statelayer.property;
38
37
 
39
38
  @include typography.scale('headline-small');
40
39
  @include typography.scale('title-large');
41
40
  @include typography.scale('title-medium');
42
41
  @include typography.scale('body-medium');
43
42
 
44
- :root {
45
- --_dialog-dir-factor: 1;
46
- }
47
- :dir(rtl) {
48
- --_dialog-dir-factor: -1;
49
- }
50
-
51
43
  dialog.micl-dialog {
52
- --statelayer-color: var(--md-sys-color-primary);
53
- --md-comp-dialog-motion-duration: #{motion.$md-sys-motion-expressive-fast-spatial-duration};
54
- --md-comp-dialog-motion-duration-reverse: #{motion.$md-sys-motion-expressive-fast-spatial-duration};
44
+ --_motion-spatial: var(--md-comp-dialog-motion-spatial, #{motion.$md-sys-motion-expressive-fast-spatial});
45
+ --_motion-duration: var(--md-comp-dialog-motion-duration, #{motion.$md-sys-motion-expressive-slow-spatial-duration});
46
+ --_motion-duration-reverse: var(--md-comp-dialog-motion-duration-reverse, #{motion.$md-sys-motion-expressive-fast-spatial-duration});
55
47
 
56
- --micl-duration: var(--md-comp-dialog-motion-duration-reverse);
57
- --micl-easing: #{motion.$md-sys-motion-easing-emphasized-decelerate};
48
+ --micl-duration: var(--_motion-duration-reverse);
49
+ --micl-spatial: #{motion.$md-sys-motion-easing-emphasized-accelerate};
50
+ --micl-easing: #{motion.$md-sys-motion-easing-emphasized-accelerate};
58
51
 
52
+ --_dialog-dir-factor: 1;
59
53
  --_dialog-background-color: var(--md-comp-dialog-container-color, var(--md-sys-color-surface-container-high));
54
+ --_margin: var(--md-comp-dialog-margin, 48px);
60
55
  --_padding: var(--md-comp-dialog-padding, 24px);
61
56
  --_translate: translate(calc(var(--_dialog-dir-factor, 1) * -50%), -50%);
62
57
 
@@ -64,48 +59,46 @@ dialog.micl-dialog {
64
59
  display: none;
65
60
  flex-direction: column;
66
61
  min-inline-size: var(--md-comp-dialog-min-width, 280px);
67
- max-inline-size: var(--md-comp-dialog-max-width, 560px);
68
- max-block-size: 100vh;
62
+ max-inline-size: min(var(--md-comp-dialog-max-width, 560px), calc(100% - var(--_margin)));
63
+ max-block-size: calc(100dvb - var(--_margin));
69
64
  position-anchor: auto;
70
- inset-block-start: anchor(start);
71
- inset-inline-start: anchor(start);
65
+ inset-block: anchor(start) auto;
66
+ inset-inline: anchor(start) auto;
72
67
  transform: var(--_translate) scale(50%);
73
68
  padding: 0;
74
69
  margin: 0;
75
70
  outline: none;
76
71
  border: none;
77
72
  border-radius: var(--md-comp-dialog-container-shape, var(--md-sys-shape-corner-extra-large));
73
+ color: var(--md-comp-dialog-content-color, var(--md-sys-color-on-surface));
78
74
  background-color: var(--_dialog-background-color);
79
- background-image: linear-gradient(rgb(from var(--statelayer-color) r g b / var(--statelayer-opacity)));
80
- background-repeat: no-repeat;
81
75
  box-shadow: var(--md-comp-dialog-container-elevation, var(--md-sys-elevation-level3));
82
76
  opacity: 0;
83
77
  overflow: hidden;
84
78
  interpolate-size: allow-keywords;
85
79
  transition:
86
- inset-block-start var(--micl-duration) linear,
87
- inset-inline-start var(--micl-duration) linear,
88
- inline-size var(--micl-duration) linear,
89
- block-size var(--micl-duration) linear,
90
- transform var(--micl-duration) linear,
91
- opacity var(--micl-duration) var(--micl-easing),
80
+ inset-block-start var(--micl-duration) var(--micl-easing),
81
+ inset-inline-start var(--micl-duration) var(--micl-easing),
82
+ inline-size var(--micl-duration) var(--micl-spatial),
83
+ block-size var(--micl-duration) var(--micl-spatial),
84
+ transform var(--micl-duration) var(--micl-spatial),
85
+ opacity var(--micl-duration) linear,
92
86
  overlay var(--micl-duration) linear allow-discrete,
93
- display var(--micl-duration) linear allow-discrete,
94
- --statelayer-opacity var(--md-comp-dialog-motion-duration) linear;
87
+ display var(--micl-duration) linear allow-discrete;
95
88
 
96
89
  @starting-style {
97
90
  block-size: fit-content;
98
91
  inline-size: fit-content;
99
- inset-block-start: anchor(start);
100
- inset-inline-start: anchor(start);
101
- opacity: 0;
102
- transform: var(--_translate) scale(50%);
103
92
  }
104
93
 
94
+ &:dir(rtl) {
95
+ --_dialog-dir-factor: -1;
96
+ }
105
97
  &:popover-open,
106
98
  &[open] {
107
- --micl-duration: var(--md-comp-dialog-motion-duration);
108
- --micl-easing: #{motion.$md-sys-motion-easing-emphasized-accelerate};
99
+ --micl-duration: var(--_motion-duration);
100
+ --micl-spatial: var(--_motion-spatial);
101
+ --micl-easing: #{motion.$md-sys-motion-easing-emphasized};
109
102
 
110
103
  display: flex;
111
104
  inset-block-start: 50%;
@@ -128,22 +121,14 @@ dialog.micl-dialog {
128
121
  inset-block-start: 50%;
129
122
  inset-inline-start: 50%;
130
123
  }
131
-
132
- &:popover-open,
133
- &[open] {
134
- @starting-style {
135
- inset-block-start: 50%;
136
- inset-inline-start: 50%;
137
- }
138
- }
139
124
  }
140
125
 
141
126
  &::backdrop {
142
127
  background-color: rgba(0, 0, 0, 0);
143
128
  transition:
144
- background-color var(--md-comp-dialog-motion-duration) linear,
145
- overlay var(--md-comp-dialog-motion-duration) linear allow-discrete,
146
- display var(--md-comp-dialog-motion-duration) linear allow-discrete;
129
+ background-color var(--micl-duration) linear,
130
+ overlay var(--micl-duration) linear allow-discrete,
131
+ display var(--micl-duration) linear allow-discrete;
147
132
  }
148
133
  &[open]::backdrop {
149
134
  background-color: rgba(0, 0, 0, var(--md-sys-state-backdrop-opacity, 32%));
@@ -157,7 +142,10 @@ dialog.micl-dialog {
157
142
  inset-block: anchor(end) auto;
158
143
  inset-inline: anchor(start) auto;
159
144
  transform: none;
160
- transition: none;
145
+ transition:
146
+ opacity var(--micl-duration) linear,
147
+ overlay var(--micl-duration) linear allow-discrete,
148
+ display var(--micl-duration) linear allow-discrete;
161
149
  position-try-fallbacks: flip-block;
162
150
  }
163
151
 
@@ -173,6 +161,7 @@ dialog.micl-dialog {
173
161
 
174
162
  &:has(> .micl-dialog__icon) {
175
163
  align-items: center;
164
+ text-align: center;
176
165
  }
177
166
  .micl-dialog__icon {
178
167
  --_icon-size: var(--md-comp-dialog-icon-size, var(--md-sys-icon-size, 24px));
@@ -192,11 +181,10 @@ dialog.micl-dialog {
192
181
  .micl-dialog__subhead {
193
182
  @include typography.title-medium;
194
183
 
195
- padding-inline: var(--_padding);
196
184
  overflow: hidden;
197
185
  text-overflow: ellipsis;
198
186
  white-space: nowrap;
199
- color: var(--md-sys-color-on-surface)
187
+ color: var(--md-comp-dialog-subhead-color, var(--md-sys-color-on-surface));
200
188
  }
201
189
  &:has(+ .micl-dialog__actions) {
202
190
  padding-block-end: 0;
@@ -218,21 +206,22 @@ dialog.micl-dialog {
218
206
  justify-content: flex-end;
219
207
  column-gap: 8px;
220
208
  padding: var(--_padding);
221
- opacity: 1;
222
- transition:
223
- opacity var(--md-comp-dialog-motion-duration) linear allow-discrete,
224
- overlay var(--md-comp-dialog-motion-duration) linear allow-discrete,
225
- display var(--md-comp-dialog-motion-duration) linear allow-discrete;
209
+ }
210
+
211
+ @media (prefers-reduced-motion: reduce) {
212
+ --_motion-duration: 0ms;
213
+ --_motion-duration-reverse: 0ms;
226
214
  }
227
215
  }
228
216
 
229
217
  dialog.micl-dialog.micl-dialog--fullscreen {
230
- @media (max-width: 560px) {
218
+ @media (max-width: layout.$md-sys-breakpoint-compact-max) {
231
219
  --_dialog-background-color: var(--md-comp-full-screen-dialog-container-color, var(--md-sys-color-surface));
232
220
 
233
- inline-size: 100vw;
234
- block-size: 100vh;
235
- max-inline-size: 100vw;
221
+ inline-size: 100%;
222
+ block-size: 100dvb;
223
+ max-inline-size: 100%;
224
+ max-block-size: 100dvb;
236
225
  border-radius: var(--md-sys-shape-corner-none, 0px);
237
226
  box-shadow: var(--md-sys-elevation-level0);
238
227
  timeline-scope: --headlineTimeline;
@@ -243,6 +232,7 @@ dialog.micl-dialog.micl-dialog--fullscreen {
243
232
  block-size: 56px;
244
233
  flex-direction: row;
245
234
  align-items: center;
235
+ text-align: start;
246
236
  gap: 8px;
247
237
  padding-block: 4px;
248
238
  padding-inline: 8px 16px;
@@ -262,26 +252,24 @@ dialog.micl-dialog.micl-dialog--fullscreen {
262
252
  white-space: nowrap;
263
253
  }
264
254
  .micl-dialog__icon {
265
- display:none;
255
+ display: none;
266
256
  }
267
257
  }
268
258
  .micl-dialog__content {
269
259
  scroll-timeline: --headlineTimeline block;
270
- scroll-timeline: --headlineTimeline vertical;
271
260
  }
272
261
  .micl-dialog__actions {
273
262
  display: none;
274
- opacity: 0;
275
263
  }
276
264
  }
277
- @media (min-width: 561px) {
265
+ @media (min-width: layout.$md-sys-breakpoint-medium-min) {
278
266
  .micl-dialog__fullscreen {
279
267
  display: none;
280
268
  }
281
269
  }
282
270
  }
283
271
 
284
- @media (max-width: 560px) {
272
+ @media (max-width: layout.$md-sys-breakpoint-compact-max) {
285
273
  body:has(dialog.micl-dialog.micl-dialog--fullscreen:popover-open) {
286
274
  overflow-y: hidden;
287
275
  }
@@ -56,17 +56,17 @@ $iconbuttons: ':is([class*="micl-iconbutton-standard-"], [class*="micl-iconbutto
56
56
  display: flex;
57
57
  align-items: center;
58
58
  justify-content: center;
59
- block-size: var(--md-sys-target-size, 48px);
59
+ block-size: var(--md-sys-state-target-size, 48px);
60
60
  inline-size: 100%;
61
- min-inline-size: var(--md-sys-target-size, 48px);
62
- inset: calc((var(--micl-height) - var(--md-sys-target-size, 48px)) / 2) 0 0 calc((min(100%, var(--md-sys-target-size, 48px)) - var(--md-sys-target-size, 48px)) / 2);
61
+ min-inline-size: var(--md-sys-state-target-size, 48px);
62
+ inset: calc((var(--micl-height) - var(--md-sys-state-target-size, 48px)) / 2) 0 0 calc((min(100%, var(--md-sys-state-target-size, 48px)) - var(--md-sys-state-target-size, 48px)) / 2);
63
63
  background-color: transparent;
64
64
  }
65
65
  }
66
66
 
67
67
  #{$iconbuttons} {
68
- --md-comp-icon-button-motion-effects: #{motion.$md-sys-motion-expressive-fast-spatial};
69
- --md-comp-icon-button-motion-duration: #{motion.$md-sys-motion-expressive-fast-spatial-duration};
68
+ --_motion-effects: var(--md-comp-icon-button-motion-effects, #{motion.$md-sys-motion-expressive-fast-spatial});
69
+ --_motion-duration: var(--md-comp-icon-button-motion-duration, #{motion.$md-sys-motion-expressive-fast-spatial-duration});
70
70
  --micl-ripple: 1;
71
71
 
72
72
  box-sizing: border-box;
@@ -96,10 +96,10 @@ $iconbuttons: ':is([class*="micl-iconbutton-standard-"], [class*="micl-iconbutto
96
96
  font-variation-settings: 'FILL' 0;
97
97
  cursor: pointer;
98
98
  transition:
99
- border-radius var(--md-comp-icon-button-motion-duration) var(--md-comp-icon-button-motion-effects),
100
- font-variation-settings var(--md-comp-icon-button-motion-duration) linear,
99
+ border-radius var(--_motion-duration) var(--_motion-effects),
100
+ font-variation-settings var(--_motion-duration) linear,
101
101
  background-size 0ms,
102
- --statelayer-opacity var(--md-comp-icon-button-motion-duration) linear;
102
+ --statelayer-opacity var(--_motion-duration) linear;
103
103
 
104
104
  &:disabled {
105
105
  box-shadow: var(--md-sys-elevation-level0);
@@ -165,8 +165,8 @@ $unselected: ':not(:checked, :has(input[type=checkbox]:checked), #{$open-accordi
165
165
  }
166
166
 
167
167
  .micl-list {
168
- --md-comp-list-motion-effects: #{motion.$md-sys-motion-expressive-fast-spatial};
169
- --md-comp-list-motion-duration: #{motion.$md-sys-motion-expressive-default-effects-duration};
168
+ --_list-motion-effects: var(--md-comp-list-motion-effects, #{motion.$md-sys-motion-expressive-fast-spatial});
169
+ --_list-motion-duration: var(--md-comp-list-motion-duration, #{motion.$md-sys-motion-expressive-default-effects-duration});
170
170
  --md-comp-accordion-motion-spatial: #{motion.$md-sys-motion-expressive-default-spatial};
171
171
  --md-comp-accordion-motion-duration: #{motion.$md-sys-motion-expressive-default-spatial-duration};
172
172
  --md-comp-divider-space: 0.5px;
@@ -269,9 +269,9 @@ $unselected: ':not(:checked, :has(input[type=checkbox]:checked), #{$open-accordi
269
269
  background-size: 0%, 100%;
270
270
  list-style: none;
271
271
  transition:
272
- border-radius var(--md-comp-list-motion-duration) var(--md-comp-list-motion-effects),
272
+ border-radius var(--_list-motion-duration) var(--_list-motion-effects),
273
273
  background-size 0ms,
274
- --statelayer-opacity var(--md-comp-list-motion-duration) linear;
274
+ --statelayer-opacity var(--_list-motion-duration) linear;
275
275
  -webkit-tap-highlight-color: transparent;
276
276
 
277
277
  &:first-of-type {
@@ -390,11 +390,15 @@ $unselected: ':not(:checked, :has(input[type=checkbox]:checked), #{$open-accordi
390
390
  }
391
391
  }
392
392
  #{$items} {
393
- input[type=checkbox].micl-checkbox {
394
- block-size: 24px;
395
- min-block-size: 24px;
396
- inline-size: 24px;
397
- min-inline-size: 24px;
393
+ // The compact list controls. The checkbox and the radio button derive all four of their
394
+ // size properties and their transparent border from these two, so overriding them shrinks
395
+ // the box without leaving the pseudo-elements wider than the padding box that centres
396
+ // them: sizing the element directly left an 18px container inside a 16px padding box,
397
+ // which start-aligned it.
398
+ input[type=checkbox].micl-checkbox,
399
+ input[type=radio].micl-radio {
400
+ --_layer: max(24px, var(--_size));
401
+ --_target: var(--_layer);
398
402
  }
399
403
  }
400
404
 
@@ -403,11 +407,11 @@ $unselected: ':not(:checked, :has(input[type=checkbox]:checked), #{$open-accordi
403
407
  font-size: var(--md-comp-list-item-leading-icon-expressive-size, 20px);
404
408
  font-variation-settings: 'FILL' 0;
405
409
  color: var(--_leading-icon-color);
406
- transition: font-variation-settings var(--md-comp-list-motion-duration) linear;
410
+ transition: font-variation-settings var(--_list-motion-duration) linear;
407
411
 
408
412
  &.micl-list-item__icon--expander {
409
413
  transform: rotate(0deg);
410
- transition: transform var(--md-comp-list-motion-duration) linear;
414
+ transition: transform var(--_list-motion-duration) linear;
411
415
  }
412
416
  }
413
417
  .micl-list-item__text ~ .micl-list-item__icon {
@@ -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
  }
@@ -11,6 +11,8 @@ To add a basic radio button, use the `<input type="radio">` element with the `mi
11
11
  <label for="myradio">First choice</label>
12
12
  ```
13
13
 
14
+ **Note on labels**: The component automatically applies `cursor: pointer` and the **on-surface** color role to any `<label>` immediately preceding, immediately following, or wrapping a `micl-radio` input. You are encouraged to customize these CSS settings to match your design system.
15
+
14
16
  ### CSS
15
17
  Import the radio button styles into your project:
16
18
 
@@ -32,9 +34,49 @@ A live example of the [Radio button component](https://henkpb.github.io/micl/rad
32
34
  ## Variants
33
35
  A radio button can be disabled by adding the `disabled` attribute to the `<input>` element.
34
36
 
35
- The Radio Button component respects the `dir` global attribute, automatically adjusting its layout for right-to-left (RTL) languages when `dir="rtl"` is applied to an ancestor element.
37
+ The Radio button component respects the element's computed direction, automatically adjusting its layout for right-to-left (RTL) languages — whether the `dir` attribute is set on the element itself or inherited from an ancestor.
38
+
39
+ To vertically align a radio button with its label, wrap both in an element with styling similar to the following:
40
+
41
+ ```CSS
42
+ .my-valign-class {
43
+ display: flex;
44
+ flex-direction: row;
45
+ align-items: center;
46
+ }
47
+ ```
48
+
49
+ ```HTML
50
+ <div class="my-valign-class">
51
+ <input type="radio" id="myradio" class="micl-radio" name="foo">
52
+ <label for="myradio">First choice</label>
53
+ </div>
54
+ ```
55
+
56
+ ## Radio group
57
+ Radio buttons are only meaningful as a group. Give every radio button for a given question the same `name`, and the browser makes the choices mutually exclusive for you — selecting one clears the others, and only the selected value is submitted.
58
+
59
+ The group is also a single stop in the tab order: <kbd>Tab</kbd> moves into and out of it, while the arrow keys move the selection between the buttons inside it. This behaviour is native, so it needs no JavaScript and no `role` attributes.
36
60
 
37
- The component applies `cursor: pointer` and the color role **on surface** to the `<label>` element immediately preceding or following an `<input type="radio">` with the `micl-radio` class. You are encouraged to customize these CSS settings to match your design system.
61
+ Wrap the group in a `<fieldset>` with a `<legend>` so that assistive technology announces the question along with each of the options:
62
+
63
+ ```HTML
64
+ <fieldset>
65
+ <legend>Delivery</legend>
66
+ <div class="my-valign-class">
67
+ <input type="radio" id="ship1" class="micl-radio" name="delivery" value="standard" checked>
68
+ <label for="ship1">Standard</label>
69
+ </div>
70
+ <div class="my-valign-class">
71
+ <input type="radio" id="ship2" class="micl-radio" name="delivery" value="express">
72
+ <label for="ship2">Express</label>
73
+ </div>
74
+ </fieldset>
75
+ ```
76
+
77
+ Always mark one option as `checked`, unless leaving the question unanswered is a valid state. A group with no preselected option cannot be returned to its initial state by the user once a choice has been made.
78
+
79
+ Adding the `required` attribute to a radio button makes the whole group mandatory — the browser will not submit the form until one of the buttons carrying that `name` is selected. The [Form foundation](../../foundations/form/README.md) leaves radio buttons to the browser's own reporting, so no MICL-specific error class is involved.
38
80
 
39
81
  ## Theming
40
82
  Each radio button can be themed with CSS custom properties that follow the Material Design 3 component-token naming convention. Set them on any appropriate parent element to affect its child radio buttons.
@@ -50,19 +92,17 @@ Each radio button can be themed with CSS custom properties that follow the Mater
50
92
 
51
93
  ```HTML
52
94
  <div style="--md-comp-radio-button-icon-size:28px">
53
- <input type="radio" id="myradio" class="micl-radio">
95
+ <input type="radio" id="myradio" class="micl-radio" name="foo">
54
96
  <label for="myradio">Large radio button</label>
55
97
  </div>
56
98
  ```
57
99
 
58
- To vertically align a radio button with its label, wrap both in an element that has a styling like suggested below:
100
+ ## Compatibility
101
+ This component relies on a few recent CSS features, which may not be fully supported in your browser:
59
102
 
60
- ```HTML
61
- <div style="display:flex;flex-direction:row;align-items:center">
62
- <input type="radio" id="myradio" class="micl-radio">
63
- <label for="myradio">Large radio button</label>
64
- </div>
65
- ```
103
+ | Feature | Used for |
104
+ |---|---|
105
+ | [Relative RGB color values](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#browser_compatibility) | The state layer and the ripple |
106
+ | [`:has()`](https://developer.mozilla.org/en-US/docs/Web/CSS/:has) | Styling a `<label>` that precedes its radio button |
66
107
 
67
- ## Compatibility
68
- This component utilizes relative RGB color values, which may not be fully supported in your browser. Please check [Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#browser_compatibility) for details.
108
+ Please check the linked browser-compatibility tables for details.