material-inspired-component-library 6.0.2 → 6.0.4

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 (60) hide show
  1. package/README.md +1 -0
  2. package/components/button/index.scss +1 -0
  3. package/components/dialog/README.md +1 -1
  4. package/components/iconbutton/index.scss +4 -0
  5. package/components/list/README.md +5 -9
  6. package/components/list/index.ts +65 -35
  7. package/components/menu/README.md +7 -7
  8. package/components/navigationrail/index.scss +23 -13
  9. package/components/navigationrail/index.ts +21 -4
  10. package/components/select/index.scss +3 -0
  11. package/components/snackbar/index.scss +142 -0
  12. package/components/snackbar/index.ts +56 -0
  13. package/components/stepper/README.md +1 -1
  14. package/components/stepper/index.ts +6 -2
  15. package/components/textfield/index.scss +1 -1
  16. package/components/textfield/index.ts +28 -19
  17. package/dist/button.css +1 -1
  18. package/dist/components/list/index.d.ts +2 -1
  19. package/dist/components/navigationrail/index.d.ts +2 -1
  20. package/dist/components/snackbar/index.d.ts +5 -0
  21. package/dist/components/textfield/index.d.ts +1 -0
  22. package/dist/iconbutton.css +1 -1
  23. package/dist/micl.css +1 -1
  24. package/dist/micl.js +1 -1
  25. package/dist/navigationrail.css +1 -1
  26. package/dist/select.css +1 -1
  27. package/dist/snackbar.css +1 -0
  28. package/dist/snackbar.js +1 -0
  29. package/dist/textfield.css +1 -1
  30. package/docs/accordion.html +5 -6
  31. package/docs/alert.html +18 -19
  32. package/docs/bottomsheet.html +28 -29
  33. package/docs/button.html +7 -8
  34. package/docs/card.html +5 -6
  35. package/docs/checkbox.html +5 -6
  36. package/docs/datepicker.html +5 -6
  37. package/docs/dialog.html +4 -5
  38. package/docs/divider.html +4 -5
  39. package/docs/docs.css +1 -0
  40. package/docs/docs.js +4 -0
  41. package/docs/iconbutton.html +10 -11
  42. package/docs/index.html +1 -1
  43. package/docs/list.html +20 -21
  44. package/docs/menu.html +30 -31
  45. package/docs/micl.css +1 -1
  46. package/docs/micl.js +1 -1
  47. package/docs/radio.html +5 -6
  48. package/docs/select.html +5 -6
  49. package/docs/sidesheet.html +11 -12
  50. package/docs/slider.html +5 -6
  51. package/docs/snackbar.html +85 -0
  52. package/docs/snackbar1.html +159 -0
  53. package/docs/snackbar2.html +159 -0
  54. package/docs/stepper.html +5 -6
  55. package/docs/switch.html +5 -6
  56. package/docs/textfield.html +5 -6
  57. package/docs/timepicker.html +5 -6
  58. package/micl.ts +4 -1
  59. package/package.json +2 -1
  60. package/styles.scss +1 -0
package/README.md CHANGED
@@ -113,6 +113,7 @@ The library currently consists of the following components:
113
113
  - [x] [Select](components/select/README.md)
114
114
  - [x] [Side sheet](components/sidesheet/README.md)
115
115
  - [x] [Slider](components/slider/README.md)
116
+ - [ ] [Snackbar]
116
117
  - [x] [Stepper](components/stepper/README.md)
117
118
  - [x] [Switch](components/switch/README.md)
118
119
  - [x] [Text field](components/textfield/README.md)
@@ -321,6 +321,7 @@ button.micl-button-text-xl {
321
321
 
322
322
  background-color: transparent;
323
323
  color: var(--md-sys-color-primary);
324
+ text-decoration: none;
324
325
 
325
326
  &:not(:disabled) {
326
327
  &:hover {
@@ -59,7 +59,7 @@ Removing the `popover` attribute creates a more intrusive **modal** dialog. This
59
59
  </div>
60
60
  </dialog>
61
61
 
62
- <button type="button" popovertarget="mydialog">Open Modal Dialog</button>
62
+ <button type="button" command="show-modal" commandfor="mydialog">Open Modal Dialog</button>
63
63
  ```
64
64
 
65
65
  - The `closedby="closerequest"` attribute restricts closing methods, typically requiring an explicit action within the dialog.
@@ -53,7 +53,9 @@ button.micl-iconbutton-outlined-xl {
53
53
  --md-sys-iconbutton-motion-duration-reverse: #{motion.$md-sys-motion-expressive-fast-spatial-duration};
54
54
  --micl-ripple: 1;
55
55
 
56
+ display: inline-flex;
56
57
  align-items: center;
58
+ justify-content: center;
57
59
  padding: 0;
58
60
  border: none;
59
61
  border-radius: var(--md-sys-shape-corner-full);
@@ -313,6 +315,8 @@ button.micl-iconbutton-standard-l,
313
315
  button.micl-iconbutton-standard-xl {
314
316
  --statelayer-color: var(--md-sys-color-on-surface-variant);
315
317
 
318
+ text-decoration: none;
319
+
316
320
  &:disabled {
317
321
  background-color: transparent;
318
322
  }
@@ -67,7 +67,7 @@ Use the anchor element to convert a list item into a hyperlink:
67
67
  ```HTML
68
68
  <ul class="micl-list">
69
69
  <li class="micl-list-item-one" tabindex="0">
70
- <a href="https://www.thetimes.com" tabindex="-1">
70
+ <a href="https://www.thetimes.com">
71
71
  <span class="micl-list-item__text">
72
72
  <span class="micl-list-item__headline">The Times</span>
73
73
  </span>
@@ -159,7 +159,7 @@ To enable selection of list items, integrate a Checkbox or Switch component with
159
159
  <li role="option" class="micl-list-item-two" tabindex="0" aria-selected="true">
160
160
  <label>
161
161
  <span class="micl-list-item__text">
162
- <span id="hd1" class="micl-list-item__headline">Blue car</span>
162
+ <span class="micl-list-item__headline">Blue car</span>
163
163
  <span class="micl-list-item__supporting-text">A blue car with four wheels.</span>
164
164
  </span>
165
165
  <input
@@ -168,8 +168,7 @@ To enable selection of list items, integrate a Checkbox or Switch component with
168
168
  class="micl-checkbox"
169
169
  value="cb1"
170
170
  checked
171
- tabindex="-1"
172
- aria-labelledby="hd1"
171
+ aria-label="Blue car"
173
172
  >
174
173
  </label>
175
174
  </li>
@@ -181,11 +180,10 @@ To enable selection of list items, integrate a Checkbox or Switch component with
181
180
  id="checkbox2"
182
181
  class="micl-switch"
183
182
  value="cb2"
184
- tabindex="-1"
185
- aria-labelledby="hd2"
183
+ aria-label="Red car"
186
184
  >
187
185
  <span class="micl-list-item__text">
188
- <span id="hd2" class="micl-list-item__headline">Red car</span>
186
+ <span class="micl-list-item__headline">Red car</span>
189
187
  <span class="micl-list-item__supporting-text">A red car with tinted windows.</span>
190
188
  </span>
191
189
  </label>
@@ -193,8 +191,6 @@ To enable selection of list items, integrate a Checkbox or Switch component with
193
191
  </ul>
194
192
  ```
195
193
 
196
- - `tabindex="-1"` on the `input` is important here, as the `<li>` should handle the focus for accessibility.
197
-
198
194
  - The `role="listbox"` is used for accessibility, indicating a selectable list.
199
195
 
200
196
  ## Customizations
@@ -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
- export const listSelector = '.micl-list-item-one,.micl-list-item-two,.micl-list-item-three';
22
+ export const listSelector = '.micl-list';
23
23
 
24
24
  export default (() =>
25
25
  {
@@ -27,7 +27,7 @@ export default (() =>
27
27
  const isSelected = (item: HTMLElement | null): boolean => !!item && item.matches(':has(input[type=checkbox]:checked)');
28
28
 
29
29
  return {
30
- keydown: (event: Event) =>
30
+ keydown: (event: Event): void =>
31
31
  {
32
32
  if (
33
33
  !(event instanceof KeyboardEvent)
@@ -37,72 +37,102 @@ export default (() =>
37
37
  return;
38
38
  }
39
39
  const parent = (event.target as Element).parentElement;
40
- if (!parent) {
41
- return;
42
- }
40
+ if (!parent) return;
43
41
 
44
42
  let items: HTMLElement[] = [];
43
+
45
44
  if (parent instanceof HTMLDetailsElement) {
46
45
  items = Array.from(parent.parentElement?.children || []).map(details => {
47
46
  let summary = details.querySelector(':scope > summary') as HTMLElement;
48
47
  return isDisabled(summary) ? null : summary;
49
48
  }).filter(item => !!item);
50
49
  }
51
- else if (parent instanceof HTMLUListElement) {
52
- items = Array.from(parent.children).map(li => {
53
- return ((li instanceof HTMLLIElement) && !isDisabled(li)) ? li : null;
50
+ else if (parent instanceof HTMLUListElement || parent instanceof HTMLOListElement) {
51
+ items = Array.from(parent.children).map(child => {
52
+ return (
53
+ (child instanceof HTMLLIElement)
54
+ && !isDisabled(child)
55
+ && (child.role !== 'separator')
56
+ ) ? child : null;
54
57
  }).filter(item => !!item);
55
58
  }
56
59
  if (items.length === 0) {
57
60
  return;
58
61
  }
59
62
 
60
- let selectedIndex = items.findIndex(item => isSelected(item)),
61
- currentIndex = items.findIndex(item => item.tabIndex === 0),
62
- nextIndex = currentIndex;
63
+ const selectedIndex = items.findIndex(item => isSelected(item));
64
+ const currentItem = document.activeElement as HTMLElement;
65
+ const currentIndex = items.indexOf(currentItem);
66
+
67
+ if (currentIndex === -1) return;
68
+
69
+ let nextIndex = currentIndex;
63
70
 
64
71
  switch (event.key) {
65
72
  case 'ArrowDown':
66
- nextIndex = (currentIndex + 1) % items.length;
67
73
  event.preventDefault(); // prevent page scrolling
74
+ nextIndex = (currentIndex + 1) % items.length;
68
75
  break;
69
76
  case 'ArrowUp':
70
- nextIndex = (currentIndex - 1 + items.length) % items.length;
71
77
  event.preventDefault();
78
+ nextIndex = (currentIndex - 1 + items.length) % items.length;
72
79
  break;
73
80
  case 'Tab':
74
- if (selectedIndex === -1) {
75
- if (currentIndex !== 0) {
76
- items[currentIndex].tabIndex = -1;
77
- items[0].tabIndex = 0;
78
- }
79
- }
80
- else if (selectedIndex !== currentIndex) {
81
- items[currentIndex].tabIndex = -1;
82
- items[selectedIndex].tabIndex = 0;
83
- }
81
+ nextIndex = (selectedIndex === -1) ? 0 : selectedIndex;
84
82
  break;
85
- case 'Enter':
86
83
  case ' ':
87
- const cb = (event.target as Element).querySelector('input[type=checkbox]');
88
- if (cb instanceof HTMLInputElement) {
89
- cb.checked = !cb.checked;
84
+ event.preventDefault();
85
+ case 'Enter':
86
+ const el = (event.target as Element).querySelector(
87
+ 'input[type=checkbox], a[href], button'
88
+ );
89
+ if (el instanceof HTMLInputElement) {
90
+ el.checked = !el.checked;
91
+ }
92
+ else if (el instanceof HTMLAnchorElement) {
93
+ el.click();
94
+ }
95
+ else if (el instanceof HTMLButtonElement) {
96
+ el.dispatchEvent(new MouseEvent('mouseenter', {
97
+ bubbles : true,
98
+ cancelable: true,
99
+ view : window
100
+ }));
90
101
  }
91
102
  break;
92
103
  default:
93
104
  }
105
+
94
106
  if (nextIndex !== currentIndex) {
95
- items[currentIndex].tabIndex = -1;
96
- items[nextIndex].tabIndex = 0;
107
+ currentItem?.setAttribute('tabindex', '-1');
108
+ items[nextIndex].setAttribute('tabindex', '0');
97
109
  items[nextIndex].focus();
110
+ }
111
+ },
112
+
113
+ initialize: (element: HTMLElement): void =>
114
+ {
115
+ if (element.dataset.miclinitialized) return;
116
+
117
+ element.dataset.miclinitialized = '1';
98
118
 
99
- const btn = items[nextIndex].querySelector(':scope > button');
100
- btn?.dispatchEvent(new MouseEvent('mouseenter', {
101
- bubbles : true,
102
- cancelable: true,
103
- view : window
104
- }));
119
+ if (element.querySelectorAll<HTMLLIElement>('li[tabindex="0"]').length === 0) {
120
+ return;
105
121
  }
122
+
123
+ const items: HTMLLIElement[] = Array.from(element.querySelectorAll(
124
+ 'li:not([role="separator"])'
125
+ ));
126
+
127
+ items.forEach(item =>
128
+ {
129
+ if (item.getAttribute('tabindex') !== '0') {
130
+ item.setAttribute('tabindex', '-1');
131
+ }
132
+
133
+ const links = item.querySelectorAll('a, button, input');
134
+ links.forEach(link => link.setAttribute('tabindex', '-1'));
135
+ });
106
136
  }
107
137
  };
108
138
  })();
@@ -66,7 +66,7 @@ Since the Menu component is based on the **List component**, all of its list ite
66
66
  <span class="micl-list-item__headline">Person</span>
67
67
  <span class="micl-list-item__supporting-text">This person is an administrator</span>
68
68
  </label>
69
- <input type="checkbox" id="cb" class="micl-checkbox" tabindex="-1">
69
+ <input type="checkbox" id="cb" class="micl-checkbox">
70
70
  </li>
71
71
  </ul>
72
72
  </nav>
@@ -74,13 +74,13 @@ Since the Menu component is based on the **List component**, all of its list ite
74
74
 
75
75
  **Example: A menu with a link**
76
76
 
77
- To make a menu item function as a link, wrap its content in an `<a>` tag and set the `tabindex` to `-1`. This ensures the link is clickable but does not interfere with menu navigation.
77
+ To make a menu item function as a link, wrap its content in an `<a>` tag. This ensures the link is clickable but does not interfere with menu navigation.
78
78
 
79
79
  ```HTML
80
80
  <nav id="mymenu" class="micl-menu" popover>
81
81
  <ul class="micl-list">
82
82
  <li class="micl-list-item-two" tabindex="0">
83
- <a href="https://www.nytimes.com" tabindex="-1">
83
+ <a href="https://www.nytimes.com" target="_blank">
84
84
  <span class="micl-list-item__icon material-symbols-outlined" aria-hidden="true">newspaper</span>
85
85
  <span class="micl-list-item__text">
86
86
  <span class="micl-list-item__headline">The New York Times</span>
@@ -94,13 +94,13 @@ To make a menu item function as a link, wrap its content in an `<a>` tag and set
94
94
 
95
95
  **Example: A menu with a submenu**
96
96
 
97
- A menu item may trigger opening a submenu when invoked by a button. Wrap the menu item content in a `<button>` tag, set its `tabindex` to `-1` and add the `popovertarget` attribute that points to the submenu. The button acts then as the control element for the submenu.
97
+ A menu item may trigger opening a submenu when invoked by a button. Wrap the menu item content in a `<button>` tag and add the `popovertarget` attribute that points to the submenu. The button acts then as the control element for the submenu.
98
98
 
99
99
  ```HTML
100
100
  <nav id="mymenu" class="micl-menu" popover>
101
101
  <ul class="micl-list">
102
102
  <li class="micl-list-item-one" tabindex="0">
103
- <button popovertarget="mysubmenu" tabindex="-1">
103
+ <button popovertarget="mysubmenu">
104
104
  <span class="micl-list-item__text">
105
105
  <span class="micl-list-item__headline">Item 1</span>
106
106
  </span>
@@ -114,7 +114,7 @@ A menu item may trigger opening a submenu when invoked by a button. Wrap the men
114
114
  </span>
115
115
  </li>
116
116
  <li role="separator" class="micl-divider"></li>
117
- <li class="micl-list-item-one" tabindex="0">
117
+ <li class="micl-list-item-one">
118
118
  <span class="micl-list-item__text">
119
119
  <span class="micl-list-item__headline">Item 1-2</span>
120
120
  </span>
@@ -122,7 +122,7 @@ A menu item may trigger opening a submenu when invoked by a button. Wrap the men
122
122
  </ul>
123
123
  </nav>
124
124
  </li>
125
- <li class="micl-list-item-one" tabindex="0">
125
+ <li class="micl-list-item-one">
126
126
  <span class="micl-list-item__text">
127
127
  <span class="micl-list-item__headline">Item 2</span>
128
128
  </span>
@@ -117,7 +117,17 @@
117
117
  background-size 3000ms,
118
118
  --statelayer-opacity var(--md-sys-navigationrail-motion-duration) linear;
119
119
 
120
- &> .micl-navigationrail__icon {
120
+ &:has(a) {
121
+ padding-block: 0;
122
+ }
123
+ a {
124
+ display: inherit;
125
+ align-items: inherit;
126
+ padding-block: 12px;
127
+ text-decoration: none;
128
+ z-index: 0;
129
+ }
130
+ .micl-navigationrail__icon {
121
131
  --micl-ripple: 1;
122
132
 
123
133
  font-size: var(--md-sys-icon-size, 24px);
@@ -140,7 +150,7 @@
140
150
  font-variation-settings var(--md-sys-navigationrail-morph-duration-reverse) linear,
141
151
  --statelayer-opacity var(--md-sys-navigationrail-motion-duration) linear;
142
152
  }
143
- &> .micl-navigationrail__text {
153
+ .micl-navigationrail__text {
144
154
  @include typography.label-medium;
145
155
 
146
156
  min-block-size: var(--md-sys-typescale-label-medium-line-height);
@@ -153,7 +163,7 @@
153
163
  }
154
164
  }
155
165
  &> input[type=radio]:checked + label.micl-navigationrail__item {
156
- &> .micl-navigationrail__icon {
166
+ .micl-navigationrail__icon {
157
167
  background-color: var(--md-sys-color-secondary-container);
158
168
  color: var(--md-sys-color-on-secondary-container);
159
169
  font-variation-settings: 'FILL' 1;
@@ -163,7 +173,7 @@
163
173
  font-variation-settings var(--md-sys-navigationrail-morph-duration) linear,
164
174
  --statelayer-opacity var(--md-sys-navigationrail-motion-duration) linear;
165
175
  }
166
- &> .micl-navigationrail__text {
176
+ .micl-navigationrail__text {
167
177
  color: var(--md-sys-color-on-secondary-container);
168
178
  }
169
179
  }
@@ -199,7 +209,7 @@ nav.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggl
199
209
  transition: background-size 0ms;
200
210
  --statelayer-opacity: var(--md-sys-state-pressed-state-layer-opacity, 10%);
201
211
  }
202
- &> .micl-navigationrail__text {
212
+ .micl-navigationrail__text {
203
213
  @include typography.label-large;
204
214
 
205
215
  margin-inline-start: -8px;
@@ -209,7 +219,7 @@ nav.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggl
209
219
  &> input[type=radio]:checked + label.micl-navigationrail__item {
210
220
  background-color: var(--md-sys-color-secondary-container);
211
221
 
212
- &> .micl-navigationrail__icon {
222
+ .micl-navigationrail__icon {
213
223
  background-color: transparent;
214
224
  }
215
225
  }
@@ -227,7 +237,7 @@ nav.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggl
227
237
  --statelayer-opacity var(--md-sys-navigationrail-motion-duration) linear;
228
238
  }
229
239
  &> input[type=radio]:checked + label.micl-navigationrail__item {
230
- &> .micl-navigationrail__icon {
240
+ .micl-navigationrail__icon {
231
241
  transition:
232
242
  background-size 3000ms,
233
243
  background-color calc(var(--md-sys-navigationrail-morph-duration) / 2) linear,
@@ -243,7 +253,7 @@ nav.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggl
243
253
  &> .micl-navigationrail__content > label.micl-navigationrail__item {
244
254
  animation: calc(var(--md-sys-navigationrail-morph-duration) / 2) linear forwards navigationrail-item-to-expanded;
245
255
 
246
- &> .micl-navigationrail__text {
256
+ .micl-navigationrail__text {
247
257
  animation: var(--md-sys-navigationrail-morph-duration) linear forwards navigationrail-text-to-expanded;
248
258
  }
249
259
  }
@@ -255,12 +265,12 @@ nav.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggl
255
265
  &> label.micl-navigationrail__item {
256
266
  animation: calc(var(--md-sys-navigationrail-morph-duration-reverse) / 2) linear forwards navigationrail-item-to-collapsed;
257
267
 
258
- &> .micl-navigationrail__text {
268
+ .micl-navigationrail__text {
259
269
  animation: var(--md-sys-navigationrail-morph-duration-reverse) linear forwards navigationrail-text-to-collapsed;
260
270
  }
261
271
  }
262
272
  &> input[type=radio]:checked + label.micl-navigationrail__item {
263
- &> .micl-navigationrail__icon {
273
+ .micl-navigationrail__icon {
264
274
  transition:
265
275
  background-size 3000ms,
266
276
  background-color calc(var(--md-sys-navigationrail-morph-duration-reverse) / 2) calc(var(--md-sys-navigationrail-morph-duration-reverse) / 2) linear,
@@ -273,17 +283,17 @@ nav.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggl
273
283
  nav.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggle:not(.micl-button--selected)) {
274
284
  &> .micl-navigationrail__content > label.micl-navigationrail__item {
275
285
  &:hover {
276
- &> .micl-navigationrail__icon {
286
+ .micl-navigationrail__icon {
277
287
  --statelayer-opacity: var(--md-sys-state-hover-state-layer-opacity, 8%);
278
288
  }
279
289
  }
280
290
  &:focus-visible {
281
- &> .micl-navigationrail__icon {
291
+ .micl-navigationrail__icon {
282
292
  --statelayer-opacity: var(--md-sys-state-focus-state-layer-opacity, 10%);
283
293
  }
284
294
  }
285
295
  &:active {
286
- &> .micl-navigationrail__icon {
296
+ .micl-navigationrail__icon {
287
297
  --statelayer-opacity: var(--md-sys-state-pressed-state-layer-opacity, 10%);
288
298
 
289
299
  background-size: 0%, 100%;
@@ -19,17 +19,17 @@
19
19
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
20
  // SOFTWARE.
21
21
 
22
- export const navigationrailSelector = '.micl-navigationrail__item[for]:not(.micl-navigationrail__item--disabled)';
22
+ export const navigationrailSelector = '.micl-navigationrail';
23
23
 
24
24
  export default (() =>
25
25
  {
26
26
  return {
27
- keydown: (event: Event) =>
27
+ keydown: (event: Event): void =>
28
28
  {
29
29
  if (
30
30
  !(event instanceof KeyboardEvent)
31
31
  || !(event.target instanceof HTMLLabelElement)
32
- || !event.target.matches(navigationrailSelector)
32
+ || !event.target.matches('label.micl-navigationrail__item[for]')
33
33
  ) {
34
34
  return;
35
35
  }
@@ -39,15 +39,32 @@ export default (() =>
39
39
  }
40
40
 
41
41
  switch (event.key) {
42
- case 'Enter':
43
42
  case ' ':
44
43
  event.preventDefault();
44
+ case 'Enter':
45
45
  if (!input.checked) {
46
46
  input.checked = !input.checked;
47
47
  }
48
+
49
+ const el = (event.target as Element).querySelector('a[href]');
50
+ if (el instanceof HTMLAnchorElement) {
51
+ el.click();
52
+ }
48
53
  break;
49
54
  default:
50
55
  }
56
+ },
57
+
58
+ initialize: (element: HTMLElement): void =>
59
+ {
60
+ if (element.dataset.miclinitialized) return;
61
+
62
+ element.dataset.miclinitialized = '1';
63
+
64
+ element.querySelectorAll<HTMLAnchorElement>('label[for] a[href]').forEach(link =>
65
+ {
66
+ link.setAttribute('tabindex', '-1');
67
+ });
51
68
  }
52
69
  };
53
70
  })();
@@ -49,6 +49,9 @@
49
49
  transition: motion.$md-sys-motion-duration-medium4 rotate;
50
50
  transform-origin: 50% calc((var(--md-sys-select-line-height) / 2) - 1px);
51
51
  }
52
+ &:disabled::picker-icon {
53
+ color: rgb(from var(--md-sys-color-on-surface-variant) r g b/var(--md-sys-state-disabled-state-layer-opacity, 38%));
54
+ }
52
55
  &:open::picker-icon {
53
56
  rotate: 180deg;
54
57
  }
@@ -0,0 +1,142 @@
1
+ //
2
+ // Copyright © 2025 Hermana AS
3
+ //
4
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ // of this software and associated documentation files (the "Software"), to deal
6
+ // in the Software without restriction, including without limitation the rights
7
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ // copies of the Software, and to permit persons to whom the Software is
9
+ // furnished to do so, subject to the following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included in all
12
+ // copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ // SOFTWARE.
21
+
22
+ @use '../../foundations';
23
+ @use '../../styles/elevation';
24
+ @use '../../styles/motion';
25
+ @use '../../styles/shapes';
26
+ @use '../../styles/typography';
27
+
28
+ :root {
29
+ --md-comp-snackbar-with-single-line-container-height: 48px;
30
+ --md-comp-snackbar-with-two-lines-container-height: 68px;
31
+ --md-comp-snackbar-margin: 24px;
32
+ }
33
+
34
+ .micl-snackbar {
35
+ box-sizing: border-box;
36
+ position: fixed;
37
+ display: flex;
38
+ align-items: center;
39
+ column-gap: 4px;
40
+ block-size: 0;
41
+ inset: auto;
42
+ inset-block-end: calc(var(--md-comp-snackbar-margin) + env(safe-area-inset-bottom));
43
+ inset-inline-start: 50%;
44
+ margin: 0;
45
+ padding-block: 0;
46
+ padding-inline: 16px 4px;
47
+ border: none;
48
+ border-radius: var(--md-sys-shape-corner-extra-small);
49
+ background-color: var(--md-sys-color-inverse-surface);
50
+ box-shadow: var(--md-sys-elevation-level3);
51
+ opacity: 0;
52
+ overflow-y: hidden;
53
+ translate: -50% 0;
54
+ transition:
55
+ opacity 500ms linear,
56
+ block-size 500ms linear,
57
+ display 300ms allow-discrete,
58
+ overlay 300ms allow-discrete;
59
+
60
+ &:popover-open {
61
+ block-size: var(--md-comp-snackbar-with-single-line-container-height);
62
+ opacity: 1;
63
+ transition:
64
+ opacity 500ms linear,
65
+ block-size 500ms linear;
66
+
67
+ @starting-style {
68
+ block-size: 0;
69
+ opacity: 0;
70
+ }
71
+ }
72
+
73
+ .micl-snackbar__supporting-text {
74
+ @include typography.body-medium;
75
+
76
+ color: var(--md-sys-color-inverse-on-surface);
77
+
78
+ &+ * {
79
+ margin-inline-start: 16px;
80
+ }
81
+ }
82
+ button {
83
+ --statelayer-color: var(--md-sys-color-inverse-primary);
84
+ color: var(--md-sys-color-inverse-primary);
85
+ }
86
+ button[class*='micl-iconbutton'] {
87
+ --statelayer-color: var(--md-sys-color-inverse-on-surface);
88
+ color: var(--md-sys-color-inverse-on-surface);
89
+ }
90
+ }
91
+
92
+ .micl-snackbarZ {
93
+ position: fixed;
94
+ display: grid;
95
+ grid-template-rows: 0fr;
96
+ align-content: flex-end;
97
+ inset: auto;
98
+ inset-block-end: 24px;
99
+ inset-block-end: calc(var(--md-comp-snackbar-margin) + env(safe-area-inset-bottom));
100
+ inset-inline-start: 50%;
101
+ margin: 0;
102
+ padding: 0;
103
+ border: none;
104
+ background: transparent;
105
+ opacity: 0;
106
+ overflow: visible;
107
+ translate: -50% 0;
108
+ transition:
109
+ opacity 300ms ease-out,
110
+ grid-template-rows 0s linear 300ms,
111
+ display 300ms allow-discrete,
112
+ overlay 300ms allow-discrete;
113
+
114
+ &:popover-open {
115
+ grid-template-rows: 1fr;
116
+ opacity: 1;
117
+ transition:
118
+ grid-template-rows 300ms cubic-bezier(0.2, 0, 0, 1),
119
+ opacity 300ms ease-out;
120
+
121
+ @starting-style {
122
+ grid-template-rows: 0fr;
123
+ opacity: 0;
124
+ }
125
+ }
126
+
127
+ .micl-snackbar__inner {
128
+ min-block-size: 0;
129
+ min-inline-size: 300px;
130
+ border-radius: 8px;
131
+ background: darkgray;
132
+ color: white;
133
+ overflow: hidden;
134
+
135
+ .micl-snackbar__content {
136
+ display: flex;
137
+ padding: 16px;
138
+ justify-content: space-between;
139
+ align-items: center;
140
+ }
141
+ }
142
+ }