material-inspired-component-library 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +10 -0
  2. package/components/button/README.md +1 -1
  3. package/components/button/index.scss +52 -79
  4. package/components/card/index.scss +28 -29
  5. package/components/checkbox/index.scss +0 -5
  6. package/components/dialog/index.scss +11 -7
  7. package/components/iconbutton/README.md +1 -1
  8. package/components/iconbutton/index.scss +46 -80
  9. package/components/list/index.scss +39 -30
  10. package/components/list/index.ts +10 -9
  11. package/components/menu/README.md +67 -4
  12. package/components/menu/index.scss +29 -29
  13. package/components/menu/index.ts +47 -16
  14. package/components/navigationrail/README.md +99 -0
  15. package/components/navigationrail/index.scss +157 -0
  16. package/components/radio/index.scss +21 -11
  17. package/components/select/index.scss +5 -11
  18. package/components/textfield/index.scss +8 -2
  19. package/dist/bottomsheet.css +1 -1
  20. package/dist/button.css +1 -1
  21. package/dist/card.css +1 -1
  22. package/dist/checkbox.css +1 -1
  23. package/dist/components/menu/index.d.ts +0 -11
  24. package/dist/dialog.css +1 -1
  25. package/dist/iconbutton.css +1 -1
  26. package/dist/list.css +1 -1
  27. package/dist/menu.css +1 -1
  28. package/dist/micl.css +1 -1
  29. package/dist/micl.js +1 -1
  30. package/dist/navigationrail.css +1 -0
  31. package/dist/navigationrail.js +1 -0
  32. package/dist/radio.css +1 -1
  33. package/dist/select.css +1 -1
  34. package/dist/slider.css +1 -1
  35. package/dist/switch.css +1 -1
  36. package/dist/textfield.css +1 -1
  37. package/docs/docs.js +2 -2
  38. package/docs/index.html +3 -1
  39. package/docs/menu.html +183 -3
  40. package/docs/micl.css +1 -1
  41. package/docs/micl.js +1 -1
  42. package/docs/navigationrail.html +75 -0
  43. package/micl.ts +10 -8
  44. package/package.json +7 -7
  45. package/styles/statelayer.scss +14 -0
  46. package/styles.scss +1 -1
  47. package/webpack.config.js +37 -0
  48. package/styles/ripple.scss +0 -50
@@ -21,23 +21,25 @@
21
21
 
22
22
  @use '../../styles/elevation';
23
23
  @use '../../styles/motion';
24
- @use '../../styles/ripple';
25
24
  @use '../../styles/shapes';
26
- @use '../../styles/statelayer';
27
25
 
28
- .micl-menu[popover] {
26
+ :root {
29
27
  --md-sys-menu-motion-spatial: #{motion.$md-sys-motion-expressive-default-spatial};
30
28
  --md-sys-menu-motion-duration: #{motion.$md-sys-motion-expressive-default-spatial-duration};
31
29
  --md-sys-menu-motion-duration-reverse: #{motion.$md-sys-motion-expressive-fast-spatial-duration};
30
+ --md-sys-menu-width-max: 280px;
31
+ --md-sys-menu-width-min: 112px;
32
+ }
32
33
 
34
+ .micl-menu[popover] {
33
35
  position: absolute;
34
36
  inset: unset;
35
37
  inset-block-start: anchor(end);
36
38
  inset-inline-start: anchor(start);
37
- position-try-fallbacks: flip-block, flip-inline;
38
- min-width: 112px;
39
- max-width: 280px;
40
- padding-inline: 0;
39
+ position-try: most-block-size flip-block, flip-inline;
40
+ min-width: var(--md-sys-menu-width-min);
41
+ max-width: var(--md-sys-menu-width-max);
42
+ padding: 0;
41
43
  border: none;
42
44
  border-radius: var(--md-sys-shape-corner-extra-small);
43
45
  background-color: var(--md-sys-color-surface-container);
@@ -45,7 +47,7 @@
45
47
  opacity: 0;
46
48
  overflow: hidden;
47
49
  transform: scaleY(0);
48
- transform-origin: top left;
50
+ transform-origin: left top;
49
51
  transition:
50
52
  opacity var(--md-sys-menu-motion-duration-reverse) linear,
51
53
  transform var(--md-sys-menu-motion-duration-reverse) var(--md-sys-menu-motion-spatial),
@@ -61,17 +63,9 @@
61
63
  overlay var(--md-sys-menu-motion-duration) linear allow-discrete,
62
64
  display var(--md-sys-menu-motion-duration) linear allow-discrete;
63
65
 
64
- @position-try-on {
65
- transform-origin: bottom left;
66
- }
67
-
68
66
  @starting-style {
69
67
  opacity: 0;
70
68
  transform: scaleY(0);
71
-
72
- @position-try-on {
73
- transform-origin: bottom left;
74
- }
75
69
  }
76
70
  &::backdrop {
77
71
  background-color: rgba(0, 0, 0, 0.2);
@@ -89,7 +83,8 @@
89
83
  display var(--md-sys-menu-motion-duration) linear allow-discrete;
90
84
  }
91
85
 
92
- .micl-list {
86
+ &> .micl-list {
87
+ --md-sys-list-padding: 4px;
93
88
  --md-sys-list-item-one-height: 48px;
94
89
  --md-sys-list-item-one-padding: 0;
95
90
  --md-sys-list-item-two-padding: 0;
@@ -99,18 +94,6 @@
99
94
  .micl-list-item-one,
100
95
  .micl-list-item-two,
101
96
  .micl-list-item-three {
102
- &:not(.micl-list-item--disabled) {
103
- --miclripple: 1;
104
-
105
- @include ripple.effect;
106
-
107
- cursor: pointer;
108
-
109
- &:focus-visible {
110
- outline-offset: calc(-1 * var(--md-sys-state-focus-indicator-thickness));
111
- z-index: 1;
112
- }
113
- }
114
97
  &.micl-list-item__divider {
115
98
  position: relative;
116
99
  margin-block-start: 16px;
@@ -126,6 +109,23 @@
126
109
  border-top: var(--md-sys-divider-thickness) solid var(--md-sys-divider-color);
127
110
  }
128
111
  }
112
+ &> .micl-menu[popover] {
113
+ transform: scaleX(0);
114
+
115
+ &:popover-open {
116
+ transform: scaleX(1);
117
+
118
+ @starting-style {
119
+ transform: scaleX(0);
120
+ }
121
+ }
122
+ &:popover-open {
123
+ &::backdrop {
124
+ background-color: rgba(0, 0, 0, 0);
125
+ }
126
+ }
127
+ }
129
128
  }
130
129
  }
131
130
  }
131
+
@@ -21,27 +21,15 @@
21
21
 
22
22
  export const menuSelector = '.micl-menu[popover]';
23
23
 
24
- /**
25
- * Set the origin for menu transformations just before transitions start.
26
- * By default, the origin is "top left" (the menu opens just below the invoker, left aligned),
27
- * but could also be "top right", "bottom left" or "bottom right".
28
- * When the browser needs to apply a position-try-fallbacks, because there is not enough space
29
- * for the menu in the default location, then the reverse transformation will be applied from
30
- * the wrong origin.
31
- * Therefore, when the menu is open, calculate the transformation origin just before the
32
- * transitions start. When the menu is closed, do the same just after the 'display:none' has
33
- * been removed by the browser (the 'toggle' event has then been triggered).
34
- */
35
24
  export default (() =>
36
25
  {
37
26
  const getOrigin = (invoker: Element, popover: Element): string =>
38
27
  {
39
- const invokerY = invoker.getBoundingClientRect().y,
40
- popoverY = popover.getBoundingClientRect().y,
41
- oldOrigin = window.getComputedStyle(popover).getPropertyValue('transform-origin');
28
+ const invokerRect = invoker.getBoundingClientRect(),
29
+ popoverRect = popover.getBoundingClientRect();
42
30
 
43
- return ((invokerY > popoverY) ? 'bottom ' : 'top ') +
44
- ((parseInt(oldOrigin) > 0) ? 'right' : 'left');
31
+ return ((invokerRect.x > popoverRect.x) ? 'right ' : 'left ') +
32
+ ((invokerRect.y > popoverRect.y) ? 'bottom' : 'top');
45
33
  };
46
34
 
47
35
  return {
@@ -72,6 +60,49 @@ export default (() =>
72
60
  }
73
61
  });
74
62
 
63
+ element.querySelectorAll<HTMLButtonElement>(
64
+ ':scope > ul.micl-list > li > button[popovertarget]'
65
+ ).forEach(submenuinvoker =>
66
+ {
67
+ if (submenuinvoker.popoverTargetElement?.matches('.micl-menu[popover]')) {
68
+ let hoverTimeout: any,
69
+ id = `--${submenuinvoker.popoverTargetElement.id}`;
70
+
71
+ if (submenuinvoker.popoverTargetElement instanceof HTMLElement) {
72
+ submenuinvoker.style.setProperty('anchor-name', id);
73
+ submenuinvoker.popoverTargetElement.style.insetBlockStart = `anchor(${id} start)`;
74
+ submenuinvoker.popoverTargetElement.style.insetInlineStart = `anchor(${id} end)`;
75
+ }
76
+
77
+ submenuinvoker.addEventListener('mouseenter', () =>
78
+ {
79
+ if (submenuinvoker.popoverTargetElement instanceof HTMLElement) {
80
+ submenuinvoker.popoverTargetElement.showPopover();
81
+ }
82
+ });
83
+ submenuinvoker.addEventListener('mouseleave', () =>
84
+ {
85
+ hoverTimeout = setTimeout(() => {
86
+ if (
87
+ submenuinvoker.popoverTargetElement instanceof HTMLElement
88
+ && !submenuinvoker.popoverTargetElement.matches(':hover')
89
+ ) {
90
+ submenuinvoker.popoverTargetElement.hidePopover();
91
+ }
92
+ }, 100);
93
+ });
94
+ submenuinvoker.popoverTargetElement.addEventListener('mouseenter', () =>
95
+ {
96
+ clearTimeout(hoverTimeout);
97
+ });
98
+ submenuinvoker.popoverTargetElement.addEventListener('mouseleave', () =>
99
+ {
100
+ if (submenuinvoker.popoverTargetElement instanceof HTMLElement) {
101
+ submenuinvoker.popoverTargetElement.hidePopover();
102
+ }
103
+ });
104
+ }
105
+ });
75
106
  }
76
107
  };
77
108
  })();
@@ -0,0 +1,99 @@
1
+ # Side sheet
2
+ This component implements the the [Material Design 3 Expressive Side sheet](https://m3.material.io/components/side-sheets/overview) design.
3
+
4
+ ## Basic Usage
5
+
6
+ ### HTML
7
+ To create a standard side sheet, use the `<dialog>` element with the `popover` attribute. The `closedby="any"` attribute allows the user to dismiss the side sheet by clicking anywhere outside of it.
8
+
9
+ ```HTML
10
+ <dialog id="mysidesheet" class="micl-sidesheet" closedby="any" popover>
11
+ <div class="micl-sidesheet__headline">
12
+ <h2>Title</h2>
13
+ <button
14
+ type="button"
15
+ class="micl-iconbutton-s material-symbols-outlined"
16
+ popovertarget="mysidesheet"
17
+ aria-label="Close"
18
+ >close</button>
19
+ </div>
20
+ <div class="micl-sidesheet__content">
21
+ ...your content...
22
+ </div>
23
+ </dialog>
24
+ ```
25
+
26
+ ### CSS
27
+ Import the side sheet styles into your project:
28
+
29
+ ```CSS
30
+ @use "material-inspired-component-library/dist/sidesheet";
31
+ ```
32
+
33
+ ### JavaScript
34
+ No custom JavaScript is required for the core functionality of the side sheet component.
35
+
36
+ ### Demo
37
+ A live example of the [Side sheet component](https://henkpb.github.io/micl/sidesheet.html) is available for you to interact with.
38
+
39
+ ## Variants
40
+ 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.
41
+
42
+ 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.
43
+
44
+ ```HTML
45
+ <dialog id="mysidesheet" class="micl-sidesheet" closedby="closerequest">
46
+ <div class="micl-sidesheet__headline">
47
+ <button
48
+ type="button"
49
+ class="micl-iconbutton-s material-symbols-outlined"
50
+ aria-label="Go back"
51
+ >arrow_back</button>
52
+ <h2>Title</h2>
53
+ <button
54
+ type="button"
55
+ class="micl-iconbutton-s material-symbols-outlined"
56
+ popovertarget="mysidesheet"
57
+ aria-label="Close"
58
+ >close</button>
59
+ </div>
60
+ <div class="micl-sidesheet__content">
61
+ ...your content...
62
+ </div>
63
+ <div class="micl-sidesheet__actions">
64
+ <button type="button" class="micl-button">Save</button>
65
+ </div>
66
+ </dialog>
67
+ ```
68
+
69
+ To open either a standard or modal side sheet, link a button to the side sheet's ID using the `popovertarget` attribute:
70
+ ```HTML
71
+ <button type="button" popovertarget="mysidesheet">Open Side Sheet</button>
72
+ ```
73
+
74
+ 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:
75
+ ```CSS
76
+ #mysidesheet {
77
+ --md-sys-sidesheet-divider-width: 0;
78
+ }
79
+ ```
80
+ To remove the horizontal divider of the actions-container:
81
+ ```CSS
82
+ #mysidesheet {
83
+ --md-sys-sidesheet-actions-divider-width: 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
+
90
+ ```CSS
91
+ box-sizing: border-box;
92
+ margin-left: 0px;
93
+ margin-right: 0px;
94
+ max-width: ...varies depending on if the side sheet is opened...
95
+ transition: ...transition on max-width...
96
+ ```
97
+
98
+ ## Compatibility
99
+ 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.
@@ -0,0 +1,157 @@
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 '../../styles/elevation';
23
+ @use '../../styles/motion';
24
+ @use '../../styles/shapes';
25
+ @use '../../styles/typography';
26
+
27
+ dialog.micl-navigationrail {
28
+ --md-sys-navigationrail-width: 256px;
29
+ --md-sys-navigationrail-maxwidth: 400px;
30
+ --md-sys-navigationrail-spring-buffer: 200px;
31
+ --md-sys-navigationrail-padding-standard: 24px;
32
+ --md-sys-navigationrail-padding-modal: 16px;
33
+ --md-sys-navigationrail-motion-spatial: #{motion.$md-sys-motion-expressive-slow-spatial};
34
+ --md-sys-navigationrail-motion-duration: #{motion.$md-sys-motion-expressive-slow-spatial-duration};
35
+ --md-sys-navigationrail-motion-duration-reverse: #{motion.$md-sys-motion-expressive-default-spatial-duration};
36
+
37
+ box-sizing: border-box;
38
+ display: none;
39
+ flex-direction: column;
40
+ justify-content: space-between;
41
+ min-width: calc(var(--md-sys-navigationrail-width) + var(--md-sys-navigationrail-spring-buffer));
42
+ max-width: calc(var(--md-sys-navigationrail-maxwidth) + var(--md-sys-navigationrail-spring-buffer));
43
+ height: 100%;
44
+ min-height: 100%;
45
+ margin-block: 0;
46
+ margin-inline-start: calc(-1 * (var(--md-sys-navigationrail-maxwidth) + var(--md-sys-navigationrail-spring-buffer)));
47
+ margin-inline-end: auto;
48
+ padding-block-start: 10px;
49
+ padding-block-end: var(--md-sys-navigationrail-padding-standard);
50
+ padding-inline-start: var(--md-sys-navigationrail-spring-buffer);
51
+ padding-inline-end: 0;
52
+ background-color: var(--md-sys-color-surface);
53
+ border: none;
54
+ box-shadow: var(--md-sys-elevation-level0);
55
+ opacity: 0;
56
+ overflow: hidden;
57
+ transition:
58
+ opacity var(--md-sys-navigationrail-motion-duration-reverse) linear,
59
+ margin-inline-start var(--md-sys-navigationrail-motion-duration-reverse) var(--md-sys-navigationrail-motion-spatial),
60
+ overlay var(--md-sys-navigationrail-motion-duration-reverse) linear allow-discrete,
61
+ display var(--md-sys-navigationrail-motion-duration-reverse) linear allow-discrete;
62
+
63
+ .micl-navigationrail__headline {
64
+ display: flex;
65
+ align-items: center;
66
+ padding-inline-start: 12px;
67
+ padding-inline-end: 24px;
68
+ column-gap: 8px;
69
+ color: var(--md-sys-color-on-surface-variant);
70
+
71
+ h1, h2, h3, h4, h5, h6, .micl-heading {
72
+ @include typography.title-large;
73
+
74
+ flex: 1 2 fit-content;
75
+ margin: 0;
76
+ overflow: hidden;
77
+ text-overflow: ellipsis;
78
+ white-space: nowrap;
79
+ user-select: none;
80
+ }
81
+ }
82
+ .micl-navigationrail__content {
83
+ box-sizing: border-box;
84
+ display: flex;
85
+ flex-direction: column;
86
+ flex: 1 1 auto;
87
+ align-items: flex-start;
88
+ row-gap: 8px;
89
+ width: 100%;
90
+ max-width: 100%;
91
+ padding-inline: var(--md-sys-navigationrail-padding-standard);
92
+ overflow: hidden auto;
93
+ }
94
+ .micl-navigationrail__actions {
95
+ box-sizing: border-box;
96
+ display: flex;
97
+ align-items: center;
98
+ justify-content: start;
99
+ width: 100%;
100
+ max-width: 100%;
101
+ height: calc(72px - var(--md-sys-navigationrail-padding-standard));
102
+ margin: auto 0 0 0;
103
+ padding-block-start: 16px;
104
+ overflow: hidden;
105
+ border-block-start: var(--md-sys-divider-thickness) solid var(--md-sys-divider-color);
106
+
107
+ button:active,
108
+ button:focus-visible,
109
+ button:hover {
110
+ color: var(--md-sys-color-primary);
111
+ }
112
+ }
113
+
114
+ &::backdrop {
115
+ background-color: rgba(0, 0, 0, 0);
116
+ transition:
117
+ background-color var(--md-sys-navigationrail-motion-duration) linear,
118
+ overlay var(--md-sys-navigationrail-motion-duration) linear allow-discrete,
119
+ display var(--md-sys-navigationrail-motion-duration) linear allow-discrete;
120
+ }
121
+ &[open] {
122
+ background-color: var(--md-sys-color-surface-container-low);
123
+ border-start-end-radius: var(--md-sys-shape-corner-large);
124
+ border-end-end-radius: var(--md-sys-shape-corner-large);
125
+ box-shadow: var(--md-sys-elevation-level1);
126
+
127
+ .micl-navigationrail__headline {
128
+ padding-inline-end: 4px;
129
+ }
130
+ }
131
+ &:popover-open {
132
+ border-inline-end: var(--md-sys-divider-thickness) solid var(--md-sys-divider-color);
133
+ }
134
+ &:popover-open,
135
+ &[open] {
136
+ display: flex;
137
+ margin-inline-start: calc(-1 * var(--md-sys-navigationrail-spring-buffer));
138
+ opacity: 1;
139
+ transition:
140
+ opacity var(--md-sys-navigationrail-motion-duration) linear,
141
+ margin-inline-start var(--md-sys-navigationrail-motion-duration) var(--md-sys-navigationrail-motion-spatial),
142
+ overlay var(--md-sys-navigationrail-motion-duration) linear allow-discrete,
143
+ display var(--md-sys-navigationrail-motion-duration) linear allow-discrete;
144
+
145
+ @starting-style {
146
+ margin-inline-start: calc(-1 * (var(--md-sys-navigationrail-maxwidth) + var(--md-sys-navigationrail-spring-buffer)));
147
+ opacity: 0;
148
+ }
149
+ }
150
+ &[open]::backdrop {
151
+ background-color: rgba(0, 0, 0, 0.2);
152
+
153
+ @starting-style {
154
+ background-color: rgba(0, 0, 0, 0);
155
+ }
156
+ }
157
+ }
@@ -20,7 +20,6 @@
20
20
  // SOFTWARE.
21
21
 
22
22
  @use '../../styles/motion';
23
- @use '../../styles/ripple';
24
23
  @use '../../styles/shapes';
25
24
  @use '../../styles/statelayer';
26
25
 
@@ -34,7 +33,6 @@ input[type=radio].micl-radio {
34
33
  --md-sys-radio-motion-effects: #{motion.$md-sys-motion-expressive-slow-effects};
35
34
  --md-sys-radio-motion-duration: #{motion.$md-sys-motion-expressive-slow-effects-duration};
36
35
  --md-sys-radio-motion-duration-reverse: #{motion.$md-sys-motion-expressive-default-effects-duration};
37
- --md-sys-ripple-background-color: var(--md-sys-color-primary);
38
36
 
39
37
  appearance: none;
40
38
  box-sizing: border-box;
@@ -47,7 +45,6 @@ input[type=radio].micl-radio {
47
45
  background-color: transparent;
48
46
  border-radius: var(--md-sys-shape-corner-full);
49
47
  outline-offset: -7px;
50
- transition: background-color var(--md-sys-radio-motion-duration) linear;
51
48
 
52
49
  &::after {
53
50
  content: "";
@@ -76,15 +73,22 @@ input[type=radio].micl-radio {
76
73
  &:not(:disabled) {
77
74
  --miclripple: 1;
78
75
 
79
- @include ripple.effect;
80
-
76
+ background-image:
77
+ radial-gradient(circle at var(--x, center) var(--y, center), transparent 0%, rgb(from var(--statelayer-color) r g b / var(--statelayer-opacity)) 10%, transparent 10%),
78
+ linear-gradient(rgb(from var(--statelayer-color) r g b / var(--statelayer-opacity)));
79
+ background-repeat: no-repeat;
80
+ background-size: 10000%, 100%;
81
81
  cursor: pointer;
82
+ transition:
83
+ background-size 3000ms,
84
+ --statelayer-opacity var(--md-sys-radio-motion-duration) linear;
82
85
 
83
86
  &:hover {
84
- background-color: rgb(from var(--md-sys-color-on-surface) r g b / var(--md-sys-state-hover-state-layer-opacity));
87
+ --statelayer-color: var(--md-sys-color-on-surface);
88
+ --statelayer-opacity: var(--md-sys-state-hover-state-layer-opacity);
85
89
 
86
90
  &:checked {
87
- background-color: rgb(from var(--md-sys-color-primary) r g b / var(--md-sys-state-hover-state-layer-opacity));
91
+ --statelayer-color: var(--md-sys-color-primary);
88
92
  }
89
93
  &::after {
90
94
  border-color: var(--md-sys-color-on-surface);
@@ -94,11 +98,13 @@ input[type=radio].micl-radio {
94
98
  }
95
99
  }
96
100
  &:focus-visible {
97
- background-color: rgb(from var(--md-sys-color-on-surface) r g b / var(--md-sys-state-focus-state-layer-opacity));
101
+ --statelayer-color: var(--md-sys-color-on-surface);
102
+ --statelayer-opacity: var(--md-sys-state-focus-state-layer-opacity);
103
+
98
104
  outline: var(--md-sys-state-focus-indicator-thickness) solid var(--md-sys-color-secondary);
99
105
 
100
106
  &:checked {
101
- background-color: rgb(from var(--md-sys-color-primary) r g b / var(--md-sys-state-focus-state-layer-opacity));
107
+ --statelayer-color: var(--md-sys-color-primary);
102
108
  }
103
109
  &::after {
104
110
  border-color: var(--md-sys-color-on-surface);
@@ -108,10 +114,14 @@ input[type=radio].micl-radio {
108
114
  }
109
115
  }
110
116
  &:active {
111
- background-color: rgb(from var(--md-sys-color-on-surface) r g b / var(--md-sys-state-pressed-state-layer-opacity));
117
+ --statelayer-color: var(--md-sys-color-on-surface);
118
+ --statelayer-opacity: var(--md-sys-state-pressed-state-layer-opacity);
119
+
120
+ background-size: 0%, 100%;
121
+ transition: background-size 0ms;
112
122
 
113
123
  &:checked {
114
- background-color: rgb(from var(--md-sys-color-primary) r g b / var(--md-sys-state-pressed-state-layer-opacity));
124
+ --statelayer-color: var(--md-sys-color-primary);
115
125
  }
116
126
  &::after {
117
127
  border-color: var(--md-sys-color-on-surface);
@@ -20,19 +20,14 @@
20
20
  // SOFTWARE.
21
21
 
22
22
  @use '../../styles/elevation';
23
- @use '../../styles/ripple';
23
+ @use '../../styles/motion';
24
24
  @use '../../styles/shapes';
25
25
  @use '../../styles/statelayer';
26
26
  @use '../../styles/typography';
27
27
 
28
28
  .micl-textfield-filled > select,
29
29
  .micl-textfield-outlined > select {
30
- --md-sys-option-one-height: var(--md-sys-list-item-one-height);
31
- --md-sys-option-one-padding: var(--md-sys-list-item-one-padding);
32
- --md-sys-option-two-padding: 8px;
33
- --md-sys-option-three-padding: 12px;
34
- --md-sys-option-space: 16px;
35
- --md-sys-option-padding-inline: 16px;
30
+ --md-sys-list-motion-duration: #{motion.$md-sys-motion-expressive-default-effects-duration};
36
31
 
37
32
  appearance: base-select;
38
33
 
@@ -63,10 +58,6 @@
63
58
  --md-sys-list-item-space: 12px;
64
59
  --md-sys-list-item-padding-inline: 16px;
65
60
  --md-sys-list-item-container-color: var(--md-sys-color-surface-container);
66
- --md-sys-state-hover-state-layer-opacity: #{statelayer.$md-sys-state-hover-state-layer-opacity};
67
- --md-sys-state-focus-state-layer-opacity: #{statelayer.$md-sys-state-focus-state-layer-opacity};
68
- --md-sys-state-pressed-state-layer-opacity: #{statelayer.$md-sys-state-pressed-state-layer-opacity};
69
- --md-sys-state-focus-indicator-thickness: #{statelayer.$md-sys-state-focus-indicator-thickness};
70
61
 
71
62
  border-radius: 0px;
72
63
 
@@ -102,6 +93,9 @@
102
93
  color: var(--md-sys-color-on-surface-variant);
103
94
  white-space: normal;
104
95
  }
96
+ &::checkmark {
97
+ color: var(--md-sys-color-on-surface);
98
+ }
105
99
  }
106
100
  }
107
101
 
@@ -253,19 +253,25 @@
253
253
  &> input:not(:disabled),
254
254
  &> select:not(:disabled),
255
255
  &> textarea:not(:disabled) {
256
+ --statelayer-opacity: var(--md-sys-state-hover-state-layer-opacity);
257
+
256
258
  border-block-end-color: var(--md-sys-color-on-surface);
257
- background-color: color-mix(in srgb, var(--md-sys-color-surface-container-highest), var(--md-sys-color-on-surface) var(--md-sys-state-hover-state-layer-opacity));
258
259
  }
259
260
  }
260
261
  &> input,
261
262
  &> select,
262
263
  &> textarea {
264
+ --statelayer-color: var(--md-sys-color-on-surface);
265
+
263
266
  padding-block-start: 18px;
264
267
  padding-block-end: 2px;
265
- background-color: var(--md-sys-color-surface-container-highest);
266
268
  border-end-start-radius: 0;
267
269
  border-end-end-radius: 0;
268
270
  outline: none;
271
+ background-color: var(--md-sys-color-surface-container-highest);
272
+ background-image: linear-gradient(rgb(from var(--statelayer-color) r g b / var(--statelayer-opacity)));
273
+ background-repeat: no-repeat;
274
+ transition: --statelayer-opacity var(--md-sys-textfield-motion-duration) linear;
269
275
 
270
276
  &:disabled {
271
277
  background-color: rgb(from var(--md-sys-color-on-surface) r g b / 4%);
@@ -1 +1 @@
1
- :root{--md-sys-elevation-level0: rgba(0, 0, 0, 0.2) 0px 0px 0px 0px, rgba(0, 0, 0, 0.14) 0px 0px 0px 0px, rgba(0, 0, 0, 0.12) 0px 0px 0px 0px;--md-sys-elevation-level1: rgba(0, 0, 0, 0.2) 0px 2px 1px -1px, rgba(0, 0, 0, 0.14) 0px 1px 1px 0px, rgba(0, 0, 0, 0.12) 0px 1px 3px 0px;--md-sys-elevation-level2: rgba(0, 0, 0, 0.2) 0px 3px 3px -2px, rgba(0, 0, 0, 0.14) 0px 3px 4px 0px, rgba(0, 0, 0, 0.12) 0px 1px 8px 0px;--md-sys-elevation-level3: rgba(0, 0, 0, 0.2) 0px 3px 5px -1px, rgba(0, 0, 0, 0.14) 0px 6px 10px 0px, rgba(0, 0, 0, 0.12) 0px 1px 18px 0px;--md-sys-elevation-level4: rgba(0, 0, 0, 0.2) 0px 5px 5px -3px, rgba(0, 0, 0, 0.14) 0px 8px 10px 1px, rgba(0, 0, 0, 0.12) 0px 3px 14px 2px;--md-sys-elevation-level5: rgba(0, 0, 0, 0.2) 0px 7px 8px -4px, rgba(0, 0, 0, 0.14) 0px 12px 17px 2px, rgba(0, 0, 0, 0.12) 0px 5px 22px 4px}:root{--md-sys-motion-duration-short1: 50ms;--md-sys-motion-duration-short2: 100ms;--md-sys-motion-duration-short3: 150ms;--md-sys-motion-duration-short4: 200ms;--md-sys-motion-duration-medium1: 250ms;--md-sys-motion-duration-medium2: 300ms;--md-sys-motion-duration-medium3: 350ms;--md-sys-motion-duration-medium4: 400ms;--md-sys-motion-duration-long1: 450ms;--md-sys-motion-duration-long2: 500ms;--md-sys-motion-duration-long3: 550ms;--md-sys-motion-duration-long4: 600ms;--md-sys-motion-duration-extra-long1: 700ms;--md-sys-motion-duration-extra-long2: 800ms;--md-sys-motion-duration-extra-long3: 900ms;--md-sys-motion-duration-extra-long4: 1000ms}:root{--md-sys-target-size: 48px;--md-sys-shape-corner-none: 0px;--md-sys-shape-corner-extra-small: 4px;--md-sys-shape-corner-small: 8px;--md-sys-shape-corner-medium: 12px;--md-sys-shape-corner-large: 16px;--md-sys-shape-corner-large-increased: 20px;--md-sys-shape-corner-extra-large: 28px;--md-sys-shape-corner-extra-large-increased: 32px;--md-sys-shape-corner-extra-extra-large: 48px;--md-sys-shape-corner-full: 50%}:root{--md-sys-state-layer-size: 40px;--md-sys-state-hover-state-layer-opacity: 8%;--md-sys-state-focus-state-layer-opacity: 10%;--md-sys-state-pressed-state-layer-opacity: 10%;--md-sys-state-dragged-state-layer-opacity: 16%;--md-sys-state-focus-indicator-outer-offset: 2px;--md-sys-state-focus-indicator-thickness: 3px}dialog.micl-bottomsheet{--md-sys-bottomsheet-height: max-content;--md-sys-bottomsheet-margin: 56px;--md-sys-bottomsheet-padding: 24px;--md-sys-bottomsheet-handle-width: 32px;--md-sys-bottomsheet-handle-height: 4px;--md-sys-bottomsheet-motion-spatial: cubic-bezier(0.39, 1.29, 0.35, 0.98);--md-sys-bottomsheet-motion-duration: 650ms;--md-sys-bottomsheet-motion-duration-reverse: 500ms;box-sizing:border-box;position:fixed;top:auto;bottom:0;height:0;max-height:50vh;width:100%;min-width:100%;margin:72px 0 0 0;padding:0;border:none;border-radius:var(--md-sys-shape-corner-extra-large) var(--md-sys-shape-corner-extra-large) 0 0;background-color:var(--md-sys-color-surface-container-low);box-shadow:var(--md-sys-elevation-level1);opacity:0;overflow-y:hidden;interpolate-size:allow-keywords}dialog.micl-bottomsheet:not(.micl-bottomsheet--resizing){transition:opacity var(--md-sys-bottomsheet-motion-duration-reverse) cubic-bezier(0.3, 0, 0.8, 0.15),height var(--md-sys-bottomsheet-motion-duration-reverse) var(--md-sys-bottomsheet-motion-spatial),overlay var(--md-sys-bottomsheet-motion-duration-reverse) linear allow-discrete,display var(--md-sys-bottomsheet-motion-duration-reverse) linear allow-discrete}dialog.micl-bottomsheet.micl-bottomsheet--resizing .micl-bottomsheet__headline{cursor:grabbing}dialog.micl-bottomsheet .micl-bottomsheet__headline{box-sizing:border-box;display:flex;align-items:center;width:100%;height:var(--md-sys-target-size);justify-content:center;cursor:grab}dialog.micl-bottomsheet .micl-bottomsheet__headline .micl-bottomsheet__draghandle{box-sizing:content-box;width:var(--md-sys-bottomsheet-handle-width);height:var(--md-sys-bottomsheet-handle-height);padding:16px calc((var(--md-sys-target-size) - var(--md-sys-bottomsheet-handle-width))/2);border:none;border-radius:var(--md-sys-shape-corner-small);background-color:var(--md-sys-color-on-surface-variant);background-clip:content-box;cursor:pointer}dialog.micl-bottomsheet .micl-bottomsheet__headline .micl-bottomsheet__draghandle:focus-visible{outline:var(--md-sys-state-focus-indicator-thickness) solid var(--md-sys-color-secondary);outline-offset:var(--md-sys-state-focus-indicator-outer-offset)}dialog.micl-bottomsheet .micl-bottomsheet__content{padding:0 var(--md-sys-bottomsheet-padding) var(--md-sys-bottomsheet-padding) var(--md-sys-bottomsheet-padding)}dialog.micl-bottomsheet::backdrop{background-color:rgba(0,0,0,0);transition:overlay var(--md-sys-bottomsheet-motion-duration) linear allow-discrete,display var(--md-sys-bottomsheet-motion-duration) linear allow-discrete,background-color var(--md-sys-bottomsheet-motion-duration) linear}dialog.micl-bottomsheet:popover-open,dialog.micl-bottomsheet[open]{height:var(--md-sys-bottomsheet-height);opacity:1}dialog.micl-bottomsheet:popover-open:not(.micl-bottomsheet--resizing),dialog.micl-bottomsheet[open]:not(.micl-bottomsheet--resizing){transition:opacity var(--md-sys-bottomsheet-motion-duration) cubic-bezier(0.05, 0.7, 0.1, 1),height var(--md-sys-bottomsheet-motion-duration) var(--md-sys-bottomsheet-motion-spatial),overlay var(--md-sys-bottomsheet-motion-duration) linear allow-discrete,display var(--md-sys-bottomsheet-motion-duration) linear allow-discrete}@starting-style{dialog.micl-bottomsheet:popover-open,dialog.micl-bottomsheet[open]{height:0;opacity:0}}dialog.micl-bottomsheet[open]::backdrop{background-color:rgba(0,0,0,.2)}@starting-style{dialog.micl-bottomsheet[open]::backdrop{background-color:rgba(0,0,0,0)}}@media(min-width: 641px){dialog.micl-bottomsheet{width:min(100vw - 2*var(--md-sys-bottomsheet-margin),640px);max-width:640px;min-width:min(100vw - 2*var(--md-sys-bottomsheet-margin),640px);inset-inline-start:calc((100vw - min(100vw - 2*var(--md-sys-bottomsheet-margin),640px))/2 - var(--md-sys-bottomsheet-margin));margin:var(--md-sys-bottomsheet-margin);margin-bottom:0}}
1
+ :root{--md-sys-elevation-level0: rgba(0, 0, 0, 0.2) 0px 0px 0px 0px, rgba(0, 0, 0, 0.14) 0px 0px 0px 0px, rgba(0, 0, 0, 0.12) 0px 0px 0px 0px;--md-sys-elevation-level1: rgba(0, 0, 0, 0.2) 0px 2px 1px -1px, rgba(0, 0, 0, 0.14) 0px 1px 1px 0px, rgba(0, 0, 0, 0.12) 0px 1px 3px 0px;--md-sys-elevation-level2: rgba(0, 0, 0, 0.2) 0px 3px 3px -2px, rgba(0, 0, 0, 0.14) 0px 3px 4px 0px, rgba(0, 0, 0, 0.12) 0px 1px 8px 0px;--md-sys-elevation-level3: rgba(0, 0, 0, 0.2) 0px 3px 5px -1px, rgba(0, 0, 0, 0.14) 0px 6px 10px 0px, rgba(0, 0, 0, 0.12) 0px 1px 18px 0px;--md-sys-elevation-level4: rgba(0, 0, 0, 0.2) 0px 5px 5px -3px, rgba(0, 0, 0, 0.14) 0px 8px 10px 1px, rgba(0, 0, 0, 0.12) 0px 3px 14px 2px;--md-sys-elevation-level5: rgba(0, 0, 0, 0.2) 0px 7px 8px -4px, rgba(0, 0, 0, 0.14) 0px 12px 17px 2px, rgba(0, 0, 0, 0.12) 0px 5px 22px 4px}:root{--md-sys-motion-duration-short1: 50ms;--md-sys-motion-duration-short2: 100ms;--md-sys-motion-duration-short3: 150ms;--md-sys-motion-duration-short4: 200ms;--md-sys-motion-duration-medium1: 250ms;--md-sys-motion-duration-medium2: 300ms;--md-sys-motion-duration-medium3: 350ms;--md-sys-motion-duration-medium4: 400ms;--md-sys-motion-duration-long1: 450ms;--md-sys-motion-duration-long2: 500ms;--md-sys-motion-duration-long3: 550ms;--md-sys-motion-duration-long4: 600ms;--md-sys-motion-duration-extra-long1: 700ms;--md-sys-motion-duration-extra-long2: 800ms;--md-sys-motion-duration-extra-long3: 900ms;--md-sys-motion-duration-extra-long4: 1000ms}:root{--md-sys-target-size: 48px;--md-sys-shape-corner-none: 0px;--md-sys-shape-corner-extra-small: 4px;--md-sys-shape-corner-small: 8px;--md-sys-shape-corner-medium: 12px;--md-sys-shape-corner-large: 16px;--md-sys-shape-corner-large-increased: 20px;--md-sys-shape-corner-extra-large: 28px;--md-sys-shape-corner-extra-large-increased: 32px;--md-sys-shape-corner-extra-extra-large: 48px;--md-sys-shape-corner-full: 50%}:root{--md-sys-state-layer-size: 40px;--md-sys-state-hover-state-layer-opacity: 8%;--md-sys-state-focus-state-layer-opacity: 10%;--md-sys-state-pressed-state-layer-opacity: 10%;--md-sys-state-dragged-state-layer-opacity: 16%;--md-sys-state-focus-indicator-inner-offset: -3px;--md-sys-state-focus-indicator-outer-offset: 2px;--md-sys-state-focus-indicator-thickness: 3px}@property --statelayer-color{syntax:"<color>";initial-value:rgba(0,0,0,0);inherits:false}@property --statelayer-opacity{syntax:"<percentage>";initial-value:0%;inherits:false}dialog.micl-bottomsheet{--md-sys-bottomsheet-height: max-content;--md-sys-bottomsheet-margin: 56px;--md-sys-bottomsheet-padding: 24px;--md-sys-bottomsheet-handle-width: 32px;--md-sys-bottomsheet-handle-height: 4px;--md-sys-bottomsheet-motion-spatial: cubic-bezier(0.39, 1.29, 0.35, 0.98);--md-sys-bottomsheet-motion-duration: 650ms;--md-sys-bottomsheet-motion-duration-reverse: 500ms;box-sizing:border-box;position:fixed;top:auto;bottom:0;height:0;max-height:50vh;width:100%;min-width:100%;margin:72px 0 0 0;padding:0;border:none;border-radius:var(--md-sys-shape-corner-extra-large) var(--md-sys-shape-corner-extra-large) 0 0;background-color:var(--md-sys-color-surface-container-low);box-shadow:var(--md-sys-elevation-level1);opacity:0;overflow-y:hidden;interpolate-size:allow-keywords}dialog.micl-bottomsheet:not(.micl-bottomsheet--resizing){transition:opacity var(--md-sys-bottomsheet-motion-duration-reverse) cubic-bezier(0.3, 0, 0.8, 0.15),height var(--md-sys-bottomsheet-motion-duration-reverse) var(--md-sys-bottomsheet-motion-spatial),overlay var(--md-sys-bottomsheet-motion-duration-reverse) linear allow-discrete,display var(--md-sys-bottomsheet-motion-duration-reverse) linear allow-discrete}dialog.micl-bottomsheet.micl-bottomsheet--resizing .micl-bottomsheet__headline{cursor:grabbing}dialog.micl-bottomsheet .micl-bottomsheet__headline{box-sizing:border-box;display:flex;align-items:center;width:100%;height:var(--md-sys-target-size);justify-content:center;cursor:grab}dialog.micl-bottomsheet .micl-bottomsheet__headline .micl-bottomsheet__draghandle{box-sizing:content-box;width:var(--md-sys-bottomsheet-handle-width);height:var(--md-sys-bottomsheet-handle-height);padding:16px calc((var(--md-sys-target-size) - var(--md-sys-bottomsheet-handle-width))/2);border:none;border-radius:var(--md-sys-shape-corner-small);background-color:var(--md-sys-color-on-surface-variant);background-clip:content-box;cursor:pointer}dialog.micl-bottomsheet .micl-bottomsheet__headline .micl-bottomsheet__draghandle:focus-visible{outline:var(--md-sys-state-focus-indicator-thickness) solid var(--md-sys-color-secondary);outline-offset:var(--md-sys-state-focus-indicator-outer-offset)}dialog.micl-bottomsheet .micl-bottomsheet__content{padding:0 var(--md-sys-bottomsheet-padding) var(--md-sys-bottomsheet-padding) var(--md-sys-bottomsheet-padding)}dialog.micl-bottomsheet::backdrop{background-color:rgba(0,0,0,0);transition:overlay var(--md-sys-bottomsheet-motion-duration) linear allow-discrete,display var(--md-sys-bottomsheet-motion-duration) linear allow-discrete,background-color var(--md-sys-bottomsheet-motion-duration) linear}dialog.micl-bottomsheet:popover-open,dialog.micl-bottomsheet[open]{height:var(--md-sys-bottomsheet-height);opacity:1}dialog.micl-bottomsheet:popover-open:not(.micl-bottomsheet--resizing),dialog.micl-bottomsheet[open]:not(.micl-bottomsheet--resizing){transition:opacity var(--md-sys-bottomsheet-motion-duration) cubic-bezier(0.05, 0.7, 0.1, 1),height var(--md-sys-bottomsheet-motion-duration) var(--md-sys-bottomsheet-motion-spatial),overlay var(--md-sys-bottomsheet-motion-duration) linear allow-discrete,display var(--md-sys-bottomsheet-motion-duration) linear allow-discrete}@starting-style{dialog.micl-bottomsheet:popover-open,dialog.micl-bottomsheet[open]{height:0;opacity:0}}dialog.micl-bottomsheet[open]::backdrop{background-color:rgba(0,0,0,.2)}@starting-style{dialog.micl-bottomsheet[open]::backdrop{background-color:rgba(0,0,0,0)}}@media(min-width: 641px){dialog.micl-bottomsheet{width:min(100vw - 2*var(--md-sys-bottomsheet-margin),640px);max-width:640px;min-width:min(100vw - 2*var(--md-sys-bottomsheet-margin),640px);inset-inline-start:calc((100vw - min(100vw - 2*var(--md-sys-bottomsheet-margin),640px))/2 - var(--md-sys-bottomsheet-margin));margin:var(--md-sys-bottomsheet-margin);margin-bottom:0}}