material-inspired-component-library 8.1.0 → 9.0.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 (284) hide show
  1. package/README.md +106 -18
  2. package/components/README.md +1 -1
  3. package/components/accordion/README.md +6 -6
  4. package/components/alert/README.md +10 -10
  5. package/components/alert/index.scss +27 -52
  6. package/components/appbar/README.md +19 -6
  7. package/components/appbar/index.scss +40 -44
  8. package/components/badge/README.md +12 -10
  9. package/components/badge/index.scss +21 -25
  10. package/components/bottomsheet/README.md +26 -1
  11. package/components/bottomsheet/index.scss +58 -44
  12. package/components/button/README.md +70 -10
  13. package/components/button/_shared.scss +210 -0
  14. package/components/button/index.scss +75 -389
  15. package/components/card/README.md +97 -85
  16. package/components/card/index.scss +46 -65
  17. package/components/checkbox/README.md +25 -14
  18. package/{tools/shapes/check.mjs → components/checkbox/_label.scss} +37 -42
  19. package/components/checkbox/index.scss +66 -66
  20. package/components/chip/README.md +186 -0
  21. package/components/chip/index.scss +285 -0
  22. package/components/datepicker/README.md +79 -0
  23. package/components/datepicker/index.scss +346 -315
  24. package/components/dialog/README.md +20 -10
  25. package/components/dialog/index.scss +55 -66
  26. package/components/divider/README.md +16 -15
  27. package/components/divider/index.scss +9 -25
  28. package/components/iconbutton/README.md +63 -12
  29. package/components/iconbutton/index.scss +142 -303
  30. package/components/list/README.md +89 -156
  31. package/components/list/index.scss +34 -36
  32. package/components/menu/README.md +81 -155
  33. package/components/menu/index.scss +52 -58
  34. package/components/navigationbar/README.md +108 -0
  35. package/components/navigationbar/index.scss +185 -0
  36. package/components/navigationrail/README.md +62 -37
  37. package/components/navigationrail/_navitem.scss +96 -0
  38. package/components/navigationrail/index.scss +78 -132
  39. package/components/progressindicator/README.md +83 -47
  40. package/components/progressindicator/index.scss +622 -172
  41. package/components/radio/README.md +11 -9
  42. package/components/radio/index.scss +36 -33
  43. package/components/select/README.md +12 -7
  44. package/components/select/index.scss +26 -34
  45. package/components/shapes/README.md +3 -3
  46. package/components/shapes/index.scss +0 -1
  47. package/components/sidesheet/README.md +21 -9
  48. package/components/sidesheet/index.scss +38 -46
  49. package/components/slider/README.md +21 -0
  50. package/components/slider/index.scss +108 -139
  51. package/components/snackbar/README.md +32 -35
  52. package/components/snackbar/index.scss +10 -22
  53. package/components/stepper/README.md +14 -7
  54. package/components/stepper/index.scss +58 -39
  55. package/components/switch/README.md +22 -15
  56. package/components/switch/index.scss +68 -60
  57. package/components/textfield/README.md +48 -5
  58. package/components/textfield/index.scss +192 -248
  59. package/components/timepicker/README.md +53 -23
  60. package/components/timepicker/index.scss +110 -128
  61. package/dist/alert.css +1 -1
  62. package/dist/alert.js +1 -1
  63. package/dist/appbar.css +1 -1
  64. package/dist/appbar.js +1 -1
  65. package/dist/badge.css +1 -1
  66. package/dist/badge.js +1 -1
  67. package/dist/base.css +1 -0
  68. package/dist/base.js +1 -0
  69. package/dist/bottomsheet.css +1 -1
  70. package/dist/bottomsheet.js +1 -1
  71. package/dist/button.css +1 -1
  72. package/dist/button.js +1 -1
  73. package/dist/card.css +1 -1
  74. package/dist/card.js +1 -1
  75. package/dist/checkbox.css +1 -1
  76. package/dist/checkbox.js +1 -1
  77. package/dist/chip.css +1 -0
  78. package/dist/chip.js +1 -0
  79. package/dist/components/button/index.d.ts +1 -1
  80. package/dist/components/iconbutton/index.d.ts +2 -7
  81. package/dist/components/slider/index.d.ts +1 -1
  82. package/dist/components/textfield/index.d.ts +2 -2
  83. package/dist/datepicker.css +1 -1
  84. package/dist/datepicker.js +1 -1
  85. package/dist/dialog.css +1 -1
  86. package/dist/dialog.js +1 -1
  87. package/dist/divider.css +1 -1
  88. package/dist/divider.js +1 -1
  89. package/dist/field.css +1 -0
  90. package/dist/field.js +1 -0
  91. package/dist/foundations/form/index.js +1 -1
  92. package/dist/foundations/runtime.d.ts +15 -0
  93. package/dist/foundations/runtime.js +1 -0
  94. package/dist/iconbutton.css +1 -1
  95. package/dist/iconbutton.js +1 -1
  96. package/dist/layout.css +1 -1
  97. package/dist/layout.js +1 -1
  98. package/dist/list.css +1 -1
  99. package/dist/list.js +1 -1
  100. package/dist/menu.css +1 -1
  101. package/dist/menu.js +1 -1
  102. package/dist/micl.css +1 -1
  103. package/dist/micl.d.ts +14 -5
  104. package/dist/micl.js +1 -1
  105. package/dist/navigationbar.css +1 -0
  106. package/dist/navigationbar.js +1 -0
  107. package/dist/navigationrail.css +1 -1
  108. package/dist/navigationrail.js +1 -1
  109. package/dist/progressindicator.css +1 -1
  110. package/dist/progressindicator.js +1 -1
  111. package/dist/radio.css +1 -1
  112. package/dist/radio.js +1 -1
  113. package/dist/scrollbar.js +1 -1
  114. package/dist/select.css +1 -1
  115. package/dist/select.js +1 -1
  116. package/dist/shapes.css +1 -1
  117. package/dist/shapes.js +1 -1
  118. package/dist/sidesheet.css +1 -1
  119. package/dist/sidesheet.js +1 -1
  120. package/dist/slider.css +1 -1
  121. package/dist/slider.js +1 -1
  122. package/dist/snackbar.css +1 -1
  123. package/dist/snackbar.js +1 -1
  124. package/dist/stepper.css +1 -1
  125. package/dist/stepper.js +1 -1
  126. package/dist/switch.css +1 -1
  127. package/dist/switch.js +1 -1
  128. package/dist/textfield.css +1 -1
  129. package/dist/textfield.js +1 -1
  130. package/dist/timepicker.css +1 -1
  131. package/dist/timepicker.js +1 -1
  132. package/foundations/_index.scss +35 -0
  133. package/foundations/{index.scss → base/index.scss} +21 -56
  134. package/foundations/field/index.scss +37 -0
  135. package/foundations/layout/index.scss +64 -65
  136. package/package.json +23 -9
  137. package/styles/statelayer.scss +20 -5
  138. package/styles.scss +5 -2
  139. package/.claude/settings.local.json +0 -14
  140. package/.editorconfig +0 -12
  141. package/.gitattributes +0 -9
  142. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -35
  143. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  144. package/CLAUDE.md +0 -53
  145. package/CODE_OF_CONDUCT.md +0 -128
  146. package/components/bottomsheet/index.ts +0 -153
  147. package/components/button/index.ts +0 -79
  148. package/components/checkbox/index.ts +0 -148
  149. package/components/datepicker/index.ts +0 -693
  150. package/components/iconbutton/index.ts +0 -77
  151. package/components/list/index.ts +0 -138
  152. package/components/menu/index.ts +0 -145
  153. package/components/navigationrail/index.ts +0 -87
  154. package/components/progressindicator/index.ts +0 -77
  155. package/components/slider/index.ts +0 -149
  156. package/components/snackbar/index.ts +0 -118
  157. package/components/stepper/index.ts +0 -248
  158. package/components/textfield/index.ts +0 -188
  159. package/components/timepicker/index.ts +0 -413
  160. package/dist/components/progressindicator/index.d.ts +0 -6
  161. package/dist/foundations.css +0 -1
  162. package/dist/foundations.js +0 -1
  163. package/docs/accordion.html +0 -344
  164. package/docs/alert.html +0 -177
  165. package/docs/bottomsheet.html +0 -240
  166. package/docs/button.html +0 -290
  167. package/docs/card-awards.webp +0 -0
  168. package/docs/card-cabinet.webp +0 -0
  169. package/docs/card-city.webp +0 -0
  170. package/docs/card-fingerprint.webp +0 -0
  171. package/docs/card-holiday.webp +0 -0
  172. package/docs/card-names.webp +0 -0
  173. package/docs/card.html +0 -159
  174. package/docs/checkbox.html +0 -147
  175. package/docs/datepicker.html +0 -274
  176. package/docs/dialog.html +0 -195
  177. package/docs/divider.html +0 -139
  178. package/docs/docs.css +0 -26
  179. package/docs/docs.js +0 -139
  180. package/docs/iconbutton.html +0 -329
  181. package/docs/index.html +0 -431
  182. package/docs/list.html +0 -310
  183. package/docs/menu.html +0 -574
  184. package/docs/micl.css +0 -1
  185. package/docs/micl.js +0 -1
  186. package/docs/navigationrail.html +0 -138
  187. package/docs/progressindicator.html +0 -288
  188. package/docs/radio.html +0 -123
  189. package/docs/select.html +0 -337
  190. package/docs/shapes.css +0 -1
  191. package/docs/shapes.html +0 -159
  192. package/docs/shapes.js +0 -1
  193. package/docs/sidesheet.html +0 -149
  194. package/docs/slider.html +0 -141
  195. package/docs/snackbar.html +0 -102
  196. package/docs/stepper.html +0 -319
  197. package/docs/switch.html +0 -196
  198. package/docs/textfield.html +0 -208
  199. package/docs/themes/airblue/dark-hc.css +0 -51
  200. package/docs/themes/airblue/dark-mc.css +0 -51
  201. package/docs/themes/airblue/dark.css +0 -51
  202. package/docs/themes/airblue/light-hc.css +0 -51
  203. package/docs/themes/airblue/light-mc.css +0 -51
  204. package/docs/themes/airblue/light.css +0 -51
  205. package/docs/themes/airblue/theme.css +0 -306
  206. package/docs/themes/barnred/dark-hc.css +0 -51
  207. package/docs/themes/barnred/dark-mc.css +0 -51
  208. package/docs/themes/barnred/dark.css +0 -51
  209. package/docs/themes/barnred/light-hc.css +0 -51
  210. package/docs/themes/barnred/light-mc.css +0 -51
  211. package/docs/themes/barnred/light.css +0 -51
  212. package/docs/themes/barnred/theme.css +0 -306
  213. package/docs/themes/citrine/dark-hc.css +0 -51
  214. package/docs/themes/citrine/dark-mc.css +0 -51
  215. package/docs/themes/citrine/dark.css +0 -51
  216. package/docs/themes/citrine/light-hc.css +0 -51
  217. package/docs/themes/citrine/light-mc.css +0 -51
  218. package/docs/themes/citrine/light.css +0 -51
  219. package/docs/themes/citrine/theme.css +0 -306
  220. package/docs/themes/gray/dark-hc.css +0 -51
  221. package/docs/themes/gray/dark-mc.css +0 -51
  222. package/docs/themes/gray/dark.css +0 -51
  223. package/docs/themes/gray/light-hc.css +0 -51
  224. package/docs/themes/gray/light-mc.css +0 -51
  225. package/docs/themes/gray/light.css +0 -51
  226. package/docs/themes/gray/theme.css +0 -306
  227. package/docs/themes/greenery/dark-hc.css +0 -51
  228. package/docs/themes/greenery/dark-mc.css +0 -51
  229. package/docs/themes/greenery/dark.css +0 -51
  230. package/docs/themes/greenery/light-hc.css +0 -51
  231. package/docs/themes/greenery/light-mc.css +0 -51
  232. package/docs/themes/greenery/light.css +0 -51
  233. package/docs/themes/greenery/theme.css +0 -306
  234. package/docs/themes/hermana/dark-hc.css +0 -51
  235. package/docs/themes/hermana/dark-mc.css +0 -51
  236. package/docs/themes/hermana/dark.css +0 -51
  237. package/docs/themes/hermana/light-hc.css +0 -51
  238. package/docs/themes/hermana/light-mc.css +0 -51
  239. package/docs/themes/hermana/light.css +0 -51
  240. package/docs/themes/hermana/theme.css +0 -306
  241. package/docs/themes/illuminating/dark-hc.css +0 -51
  242. package/docs/themes/illuminating/dark-mc.css +0 -51
  243. package/docs/themes/illuminating/dark.css +0 -51
  244. package/docs/themes/illuminating/light-hc.css +0 -51
  245. package/docs/themes/illuminating/light-mc.css +0 -51
  246. package/docs/themes/illuminating/light.css +0 -51
  247. package/docs/themes/illuminating/theme.css +0 -306
  248. package/docs/themes/magenta/dark-hc.css +0 -51
  249. package/docs/themes/magenta/dark-mc.css +0 -51
  250. package/docs/themes/magenta/dark.css +0 -51
  251. package/docs/themes/magenta/light-hc.css +0 -51
  252. package/docs/themes/magenta/light-mc.css +0 -51
  253. package/docs/themes/magenta/light.css +0 -51
  254. package/docs/themes/magenta/theme.css +0 -306
  255. package/docs/themes/mocha/dark-hc.css +0 -51
  256. package/docs/themes/mocha/dark-mc.css +0 -51
  257. package/docs/themes/mocha/dark.css +0 -51
  258. package/docs/themes/mocha/light-hc.css +0 -51
  259. package/docs/themes/mocha/light-mc.css +0 -51
  260. package/docs/themes/mocha/light.css +0 -51
  261. package/docs/themes/mocha/theme.css +0 -306
  262. package/docs/themes/olivegreen/dark-hc.css +0 -51
  263. package/docs/themes/olivegreen/dark-mc.css +0 -51
  264. package/docs/themes/olivegreen/dark.css +0 -51
  265. package/docs/themes/olivegreen/light-hc.css +0 -51
  266. package/docs/themes/olivegreen/light-mc.css +0 -51
  267. package/docs/themes/olivegreen/light.css +0 -51
  268. package/docs/themes/olivegreen/theme.css +0 -306
  269. package/docs/themes/peri/dark-hc.css +0 -51
  270. package/docs/themes/peri/dark-mc.css +0 -51
  271. package/docs/themes/peri/dark.css +0 -51
  272. package/docs/themes/peri/light-hc.css +0 -51
  273. package/docs/themes/peri/light-mc.css +0 -51
  274. package/docs/themes/peri/light.css +0 -51
  275. package/docs/themes/peri/theme.css +0 -306
  276. package/docs/timepicker.html +0 -160
  277. package/foundations/form/index.ts +0 -174
  278. package/foundations/layout/README.md +0 -127
  279. package/intl.d.ts +0 -9
  280. package/micl.ts +0 -221
  281. package/styles/README.md +0 -196
  282. package/tools/shapes/generate.mjs +0 -828
  283. package/tsconfig.json +0 -116
  284. package/webpack.config.js +0 -104
@@ -19,24 +19,16 @@
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';
23
22
  @use '../../styles/motion';
24
23
  @use '../../styles/statelayer';
25
24
 
26
25
  @include statelayer.token('disabled-state-layer-opacity');
27
26
 
28
- :root {
29
- --md-sys-stepper-counter-style: decimal;
30
- --md-sys-stepper-dot-size: 12px;
31
- }
32
- body {
33
- --md-sys-stepper-dot-done-color: var(--md-sys-color-tertiary-container, blue);
34
- }
35
-
36
27
  .micl-stepper {
37
- --md-sys-stepper-motion-spatial: #{motion.$md-sys-motion-expressive-slow-spatial};
38
- --md-sys-stepper-motion-duration: #{motion.$md-sys-motion-expressive-slow-spatial-duration};
39
- --md-sys-stepper-motion-duration-reverse: #{motion.$md-sys-motion-expressive-default-spatial-duration};
28
+ --md-comp-stepper-motion-spatial: #{motion.$md-sys-motion-expressive-slow-spatial};
29
+ --md-comp-stepper-motion-duration: #{motion.$md-sys-motion-expressive-slow-spatial-duration};
30
+
31
+ --_dot-size: var(--md-comp-stepper-dot-size, 12px);
40
32
 
41
33
  box-sizing: border-box;
42
34
  display: flex;
@@ -45,28 +37,53 @@ body {
45
37
  margin: 0;
46
38
 
47
39
  .micl-stepper__header {
48
- --md-sys-stepper-dot-size: 24px;
40
+ --_dot-size: var(--md-comp-stepper-header-dot-size, 24px);
49
41
 
42
+ position: relative;
50
43
  display: flex;
51
44
  justify-content: space-between;
52
45
  align-items: flex-start;
53
46
  margin-inline: -10px;
54
- background-image: linear-gradient(90deg, var(--md-sys-divider-color), var(--md-sys-divider-color));
55
- background-position: center;
56
- background-repeat: no-repeat;
57
- background-size: 100% 1px;
58
47
  counter-reset: dotnumber;
48
+ anchor-scope: all;
59
49
 
60
50
  button {
61
- background-color: var(--_card-background-color, inherit);
51
+ // The connector segments and the touch-target overlay are anchored
52
+ // pseudo-elements: an anchor is only acceptable when it is a
53
+ // descendant of the positioned element's containing block, so the
54
+ // buttons must stay static to make the header that containing block.
55
+ // The unique per-button anchor names are assigned by the stepper script.
56
+ position: static;
57
+ anchor-name: var(--micl-stepper-anchor);
62
58
  pointer-events: none;
63
59
 
60
+ // The shared touch-target overlay assumes a positioned button;
61
+ // re-anchor it to this button's box.
62
+ &::before {
63
+ inset: auto;
64
+ inset-block-start: calc(anchor(var(--micl-stepper-anchor) center) - var(--md-sys-target-size, 48px) / 2);
65
+ inset-inline-start: anchor(var(--micl-stepper-anchor) start);
66
+ inset-inline-end: anchor(var(--micl-stepper-anchor) end);
67
+ inline-size: auto;
68
+ }
69
+ // The connector line is drawn as one segment per step, spanning only
70
+ // the real gap between this button and the previous one.
71
+ &:not(:first-child)::after {
72
+ content: "";
73
+ position: absolute;
74
+ inset-block-start: calc(anchor(var(--micl-stepper-anchor) center) - 0.5px);
75
+ inset-inline-start: anchor(var(--micl-stepper-prev) end);
76
+ inset-inline-end: anchor(var(--micl-stepper-anchor) start);
77
+ block-size: 1px;
78
+ background-color: var(--md-comp-divider-color, var(--md-sys-color-outline-variant));
79
+ pointer-events: none;
80
+ }
64
81
  &.micl-stepper__progress--done {
65
82
  pointer-events: inherit;
66
83
  }
67
84
  }
68
85
  .micl-stepper__progress-dot::before {
69
- content: counter(dotnumber, var(--md-sys-stepper-counter-style));
86
+ content: counter(dotnumber, var(--md-comp-stepper-counter-style, decimal));
70
87
  }
71
88
  }
72
89
  &.micl-stepper--nonlinear .micl-stepper__header button {
@@ -88,8 +105,8 @@ body {
88
105
  opacity: 0%;
89
106
  transform: translateX(100%);
90
107
  transition:
91
- opacity var(--md-sys-stepper-motion-duration) linear,
92
- transform var(--md-sys-stepper-motion-duration) var(--md-sys-stepper-motion-spatial);
108
+ opacity var(--md-comp-stepper-motion-duration) linear,
109
+ transform var(--md-comp-stepper-motion-duration) var(--md-comp-stepper-motion-spatial);
93
110
 
94
111
  &:has(~ .micl-stepper__step[aria-current=step]) {
95
112
  transform: translateX(-100%);
@@ -130,34 +147,36 @@ body {
130
147
  column-gap: 4px;
131
148
  }
132
149
  .micl-stepper__progress-dot {
133
- block-size: var(--md-sys-stepper-dot-size);
134
- inline-size: var(--md-sys-stepper-dot-size);
135
- min-inline-size: var(--md-sys-stepper-dot-size);
136
- line-height: var(--md-sys-stepper-dot-size);
137
- border-radius: calc(var(--md-sys-stepper-dot-size) / 2);
150
+ block-size: var(--_dot-size);
151
+ inline-size: var(--_dot-size);
152
+ min-inline-size: var(--_dot-size);
153
+ line-height: var(--_dot-size);
154
+ border-radius: calc(var(--_dot-size) / 2);
138
155
  text-align: center;
139
- background-color: var(--md-sys-color-on-surface);
140
- color: var(--md-sys-color-surface);
156
+ background-color: var(--md-comp-stepper-dot-color, var(--md-sys-color-on-surface));
157
+ color: var(--md-comp-stepper-dot-label-color, var(--md-sys-color-surface));
141
158
  opacity: var(--md-sys-state-disabled-state-layer-opacity, 38%);
142
159
  counter-increment: dotnumber 1;
143
160
  }
144
161
  .micl-stepper__progress--done.micl-stepper__progress-dot,
145
162
  .micl-stepper__progress--done .micl-stepper__progress-dot {
146
- background-color: var(--md-sys-stepper-dot-done-color);
147
- color: var(--md-sys-color-on-tertiary-container);
163
+ background-color: var(--md-comp-stepper-dot-done-color, var(--md-sys-color-tertiary-container));
164
+ color: var(--md-comp-stepper-dot-done-label-color, var(--md-sys-color-on-tertiary-container));
148
165
  opacity: 100%;
149
166
  }
150
167
  }
151
168
 
152
- [dir=rtl] {
153
- .micl-stepper .micl-stepper__steps .micl-stepper__step {
154
- transform: translateX(-100%);
169
+ .micl-stepper .micl-stepper__steps .micl-stepper__step:dir(rtl) {
170
+ transform: translateX(-100%);
155
171
 
156
- &:has(~ .micl-stepper__step[aria-current=step]) {
157
- transform: translateX(100%);
158
- }
159
- &[aria-current=step] {
160
- transform: translateX(0%);
161
- }
172
+ &:has(~ .micl-stepper__step[aria-current=step]) {
173
+ transform: translateX(100%);
162
174
  }
175
+ &[aria-current=step] {
176
+ transform: translateX(0%);
177
+ }
178
+ }
179
+
180
+ .micl-stepper__action--hidden, .micl-stepper__step--hidden {
181
+ display: none !important;
163
182
  }
@@ -34,38 +34,45 @@ By default, the component displays an icon on the switch handle in both the sele
34
34
 
35
35
  ```CSS
36
36
  #myswitch {
37
- --md-sys-switch-unselected-icon: "";
37
+ --md-comp-switch-unselected-icon: "";
38
38
  }
39
39
  ```
40
40
  To remove the icon in the selected state:
41
41
  ```CSS
42
42
  #myswitch {
43
- --md-sys-switch-selected-icon: "";
43
+ --md-comp-switch-selected-icon: "";
44
44
  }
45
45
  ```
46
46
 
47
47
  A switch can be disabled by adding the `disabled` attribute to the `<input>` element.
48
48
 
49
- The Switch 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.
49
+ The Switch component respects the element's computed direction, automatically adjusting its layout for right-to-left (RTL) languages whether the `dir` attribute (including `dir="auto"`) is set on the element itself or inherited from an ancestor.
50
50
 
51
51
  The component applies `cursor: pointer` and the color role **on surface** to the `<label>` element immediately preceding or following the `<input type="checkbox">` with the `micl-switch` class. You are encouraged to customize these CSS settings to match your design system.
52
52
 
53
- ## Customizations
54
- You can customize the appearance of the Switch component by overriding its global CSS variables. These variables are declared on the `:root` pseudo-class and can be changed on any appropriate parent element to affect its child switches.
55
-
56
- | Variable name | Default Value | Description |
57
- | ------------- | ------------- | ----------- |
58
- | --md-sys-switch-handle-size | 16px | The diameter of the handle when the switch is "off" |
59
- | --md-sys-switch-handle-selected-size | 24px | The diameter of the handle when the switch is "on" |
60
- | --md-sys-switch-handle-pressed-size | 28px | The diameter of the handle when the switch is pressed |
61
- | --md-sys-switch-outline-width | 2px | The width of the border |
62
- | --md-sys-switch-target-height | 32px | The height of the track |
63
- | --md-sys-switch-target-width | 52px | The width of the track |
53
+ ## Theming
54
+ Each switch 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 switches.
55
+
56
+ | Custom property | Meaning | Default |
57
+ |---|---|---|
58
+ | `--md-comp-switch-track-width` | The width of the track | `52px` |
59
+ | `--md-comp-switch-track-height` | The height of the track | `32px` |
60
+ | `--md-comp-switch-track-outline-width` | The border width of the track | `2px` |
61
+ | `--md-comp-switch-handle-size` | The diameter of the handle when the switch is "off" | `16px` |
62
+ | `--md-comp-switch-selected-handle-size` | The diameter of the handle when the switch is "on" | `24px` |
63
+ | `--md-comp-switch-pressed-handle-size` | The diameter of the handle when the switch is pressed | `28px` |
64
+ | `--md-comp-switch-unselected-track-color` | The track color when the switch is "off" | `--md-sys-color-surface-container-highest` |
65
+ | `--md-comp-switch-unselected-track-outline-color` | The track border color when the switch is "off" | `--md-sys-color-outline` |
66
+ | `--md-comp-switch-unselected-handle-color` | The handle color when the switch is "off" | `--md-sys-color-outline` |
67
+ | `--md-comp-switch-unselected-icon-color` | The icon color when the switch is "off" | `--md-sys-color-surface-container-highest` |
68
+ | `--md-comp-switch-selected-track-color` | The track color when the switch is "on" | `--md-sys-color-primary` |
69
+ | `--md-comp-switch-selected-handle-color` | The handle color when the switch is "on" | `--md-sys-color-on-primary` |
70
+ | `--md-comp-switch-selected-icon-color` | The icon color when the switch is "on" | `--md-sys-color-on-primary-container` |
64
71
 
65
72
  **Example: Changing the width of the switch**
66
73
 
67
74
  ```HTML
68
- <div style="--md-sys-switch-target-width:64px">
75
+ <div style="--md-comp-switch-track-width:64px">
69
76
  <input type="checkbox" id="myswitch" class="micl-switch" role="switch">
70
77
  <label for="myswitch">Long switch</label>
71
78
  </div>
@@ -19,11 +19,11 @@
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';
23
22
  @use '../../styles/motion';
24
23
  @use '../../styles/shape';
25
24
  @use '../../styles/statelayer';
26
25
  @use '../../styles/typography';
26
+ @use '../checkbox/label';
27
27
 
28
28
  @include shape.corner('full');
29
29
 
@@ -34,81 +34,86 @@
34
34
  @include statelayer.token('disabled-state-layer-opacity');
35
35
  @include statelayer.token('focus-indicator-thickness');
36
36
 
37
- :root {
38
- --md-sys-switch-handle-size: 16px;
39
- --md-sys-switch-handle-selected-size: 24px;
40
- --md-sys-switch-handle-pressed-size: 28px;
41
- --md-sys-switch-outline-width: 2px;
42
- --md-sys-switch-target-height: 32px;
43
- --md-sys-switch-target-width: 52px;
44
- }
37
+ $switch: 'input[type=checkbox].micl-switch';
38
+
39
+ #{$switch} {
40
+ --md-comp-switch-unselected-icon: "+";
41
+ --md-comp-switch-selected-icon: "\AC";
42
+ --md-comp-switch-motion-effects: #{motion.$md-sys-motion-expressive-slow-effects};
43
+ --md-comp-switch-motion-duration: #{motion.$md-sys-motion-expressive-slow-effects-duration};
45
44
 
46
- input[type=checkbox].micl-switch {
47
- --md-sys-switch-unselected-icon: "+";
48
- --md-sys-switch-selected-icon: "\AC";
49
- --md-sys-switch-motion-effects: #{motion.$md-sys-motion-expressive-slow-effects};
50
- --md-sys-switch-motion-duration: #{motion.$md-sys-motion-expressive-slow-effects-duration};
51
- --md-sys-switch-motion-duration-reverse: #{motion.$md-sys-motion-expressive-default-effects-duration};
45
+ --_track-width: var(--md-comp-switch-track-width, 52px);
46
+ --_track-height: var(--md-comp-switch-track-height, 32px);
47
+ --_track-outline-width: var(--md-comp-switch-track-outline-width, 2px);
48
+ --_handle-size: var(--md-comp-switch-handle-size, 16px);
49
+ --_handle-selected-size: var(--md-comp-switch-selected-handle-size, 24px);
50
+ --_handle-pressed-size: var(--md-comp-switch-pressed-handle-size, 28px);
51
+ --_layer: var(--md-sys-state-layer-size, 40px);
52
+ --_target: var(--md-sys-target-size, 48px);
52
53
 
53
54
  appearance: none;
54
55
  position: relative;
55
- inline-size: var(--md-sys-switch-target-width);
56
- block-size: var(--md-sys-target-size);
56
+ inline-size: var(--_track-width);
57
+ block-size: var(--_target);
57
58
  margin: 0;
58
- border-radius: calc(var(--md-sys-switch-target-height) / 2);
59
+ border-radius: calc(var(--_track-height) / 2);
59
60
  outline: none;
60
61
  -webkit-tap-highlight-color: transparent;
61
62
 
63
+ // The track.
62
64
  &::before {
63
65
  content: "";
64
66
  box-sizing: border-box;
65
67
  display: block;
66
- inline-size: var(--md-sys-switch-target-width);
67
- block-size: var(--md-sys-switch-target-height);
68
- margin-block: calc((var(--md-sys-target-size, 48px) - var(--md-sys-switch-target-height)) / 2);
69
- border: var(--md-sys-switch-outline-width) solid var(--md-sys-color-outline);
68
+ inline-size: var(--_track-width);
69
+ block-size: var(--_track-height);
70
+ margin-block: calc((var(--_target) - var(--_track-height)) / 2);
71
+ border: var(--_track-outline-width) solid var(--md-comp-switch-unselected-track-outline-color, var(--md-sys-color-outline));
70
72
  border-radius: inherit;
71
- background-color: var(--md-sys-color-surface-container-highest);
72
- transition: background-color var(--md-sys-switch-motion-duration) motion.$md-sys-motion-easing-emphasized;
73
+ background-color: var(--md-comp-switch-unselected-track-color, var(--md-sys-color-surface-container-highest));
74
+ transition: background-color var(--md-comp-switch-motion-duration) motion.$md-sys-motion-easing-emphasized;
73
75
  }
76
+ // The handle: a state-layer-sized box whose transparent border shrinks the painted
77
+ // content box to the handle size; the icon glyphs are rotated typeface characters,
78
+ // with their metrics tuned in pixels against a 16px base.
74
79
  &::after {
75
- content: var(--md-sys-switch-unselected-icon);
80
+ content: var(--md-comp-switch-unselected-icon);
76
81
  box-sizing: border-box;
77
82
  position: absolute;
78
- inline-size: var(--md-sys-state-layer-size, 40px);
79
- block-size: var(--md-sys-state-layer-size, 40px);
83
+ inline-size: var(--_layer);
84
+ block-size: var(--_layer);
80
85
  inset: 0;
81
- inset-inline-start: calc((var(--md-sys-target-size, 48px) - var(--md-sys-state-layer-size, 40px) - 16px) / 2);
86
+ inset-inline-start: calc((var(--_target) - var(--_layer) - 16px) / 2);
82
87
  margin: auto 0;
83
- font: 300 16px / 1rem var(--md-ref-typeface-plain);
84
- color: var(--md-sys-color-surface-container-highest);
88
+ font: 300 16px / 16px var(--md-ref-typeface-plain);
89
+ color: var(--md-comp-switch-unselected-icon-color, var(--md-sys-color-surface-container-highest));
85
90
  text-align: center;
86
- background-color: var(--md-sys-color-outline);
91
+ background-color: var(--md-comp-switch-unselected-handle-color, var(--md-sys-color-outline));
87
92
  background-clip: content-box;
88
- border: calc((var(--md-sys-state-layer-size, 40px) - var(--md-sys-switch-handle-size)) / 2) solid transparent;
93
+ border: calc((var(--_layer) - var(--_handle-size)) / 2) solid transparent;
89
94
  border-radius: var(--md-sys-shape-corner-full);
90
95
  transform: rotate(135deg);
91
96
  transition:
92
- inset-inline-start var(--md-sys-switch-motion-duration) var(--md-sys-switch-motion-effects),
93
- border-width var(--md-sys-switch-motion-duration) var(--md-sys-switch-motion-effects),
94
- line-height var(--md-sys-switch-motion-duration) var(--md-sys-switch-motion-effects),
95
- color var(--md-sys-switch-motion-duration) motion.$md-sys-motion-easing-emphasized,
96
- border-color var(--md-sys-switch-motion-duration) motion.$md-sys-motion-easing-emphasized,
97
- background-color var(--md-sys-switch-motion-duration) motion.$md-sys-motion-easing-emphasized;
97
+ inset-inline-start var(--md-comp-switch-motion-duration) var(--md-comp-switch-motion-effects),
98
+ border-width var(--md-comp-switch-motion-duration) var(--md-comp-switch-motion-effects),
99
+ line-height var(--md-comp-switch-motion-duration) var(--md-comp-switch-motion-effects),
100
+ color var(--md-comp-switch-motion-duration) motion.$md-sys-motion-easing-emphasized,
101
+ border-color var(--md-comp-switch-motion-duration) motion.$md-sys-motion-easing-emphasized,
102
+ background-color var(--md-comp-switch-motion-duration) motion.$md-sys-motion-easing-emphasized;
98
103
  }
99
104
  &:checked {
100
105
  &::before {
101
- background-color: var(--md-sys-color-primary);
106
+ background-color: var(--md-comp-switch-selected-track-color, var(--md-sys-color-primary));
102
107
  }
103
108
  &::after {
104
- content: var(--md-sys-switch-selected-icon);
105
- inset-inline-start: calc(var(--md-sys-switch-target-width) - ((var(--md-sys-state-layer-size, 40px) + var(--md-sys-target-size, 48px) - 16px) / 2));
106
- font-size: 1.6rem;
107
- line-height: 1.3rem;
108
- letter-spacing: 0.1rem;
109
- border: calc((var(--md-sys-state-layer-size, 40px) - var(--md-sys-switch-handle-selected-size)) / 2) solid transparent;
110
- color: var(--md-sys-color-on-primary-container);
111
- background-color: var(--md-sys-color-on-primary);
109
+ content: var(--md-comp-switch-selected-icon);
110
+ inset-inline-start: calc(var(--_track-width) - ((var(--_layer) + var(--_target) - 16px) / 2));
111
+ font-size: 25.6px;
112
+ line-height: 20.8px;
113
+ letter-spacing: 1.6px;
114
+ border: calc((var(--_layer) - var(--_handle-selected-size)) / 2) solid transparent;
115
+ color: var(--md-comp-switch-selected-icon-color, var(--md-sys-color-on-primary-container));
116
+ background-color: var(--md-comp-switch-selected-handle-color, var(--md-sys-color-on-primary));
112
117
  }
113
118
  }
114
119
  &:not(:disabled) {
@@ -142,18 +147,17 @@ input[type=checkbox].micl-switch {
142
147
  }
143
148
  &:active {
144
149
  &::after {
145
- line-height: 1.7rem;
146
- border: calc((var(--md-sys-state-layer-size, 40px) - var(--md-sys-switch-handle-pressed-size)) / 2) solid transparent;
150
+ line-height: 27.2px;
151
+ border: calc((var(--_layer) - var(--_handle-pressed-size)) / 2) solid transparent;
147
152
  background-color: var(--md-sys-color-on-surface-variant);
148
153
  }
149
154
  &:checked::after {
150
- line-height: 1.6rem;
151
- border-width: calc((var(--md-sys-state-layer-size, 40px) - var(--md-sys-switch-handle-pressed-size)) / 2);
155
+ line-height: 25.6px;
156
+ border-width: calc((var(--_layer) - var(--_handle-pressed-size)) / 2);
152
157
  border-color: color-mix(in srgb, var(--md-sys-color-primary) var(--md-sys-state-pressed-state-layer-opacity, 10%), transparent);
153
158
  background-color: var(--md-sys-color-primary-container);
154
159
  }
155
160
  &:not(:checked)::after {
156
- inset-inline-start: calc((var(--md-sys-target-size, 48px) - var(--md-sys-state-layer-size, 40px) - 16px) / 2);
157
161
  border-color: color-mix(in srgb, var(--md-sys-color-on-surface) var(--md-sys-state-pressed-state-layer-opacity, 10%), transparent);
158
162
  }
159
163
  }
@@ -180,15 +184,19 @@ input[type=checkbox].micl-switch {
180
184
  }
181
185
  }
182
186
 
183
- input[type=checkbox].micl-switch:not(:disabled) + label,
184
- label:has(+ input[type=checkbox].micl-switch:not(:disabled)) {
185
- -webkit-tap-highlight-color: transparent;
186
- cursor: pointer;
187
+ #{$switch}:not(:disabled) + label,
188
+ label:has(+ #{$switch}:not(:disabled)) {
189
+ @extend %micl-toggle-label-pointer;
187
190
  }
188
- input[type=checkbox].micl-switch + label,
189
- label:has(+ input[type=checkbox].micl-switch) {
190
- color: var(--md-sys-color-on-surface);
191
+ #{$switch} + label,
192
+ label:has(+ #{$switch}) {
193
+ @extend %micl-toggle-label;
191
194
  }
192
- [dir=rtl] input[type=checkbox].micl-switch::after {
195
+ #{$switch}:disabled + label,
196
+ label:has(+ #{$switch}:disabled) {
197
+ @extend %micl-toggle-label-disabled;
198
+ }
199
+
200
+ #{$switch}:dir(rtl)::after {
193
201
  transform: rotate(45deg) scaleY(-1);
194
202
  }
@@ -62,11 +62,15 @@ Adding the `micl-textfield--error` class to the text field displays it in an err
62
62
  ### Leading Content
63
63
  The data-input element can be preceded by various elements:
64
64
 
65
- - **Icon**: Use `micl-textfield__icon-leading` with a (Material Symbols) icon.
65
+ - **Icon**: Use `micl-textfield__icon-leading` with a (Material Symbols) icon. When using a different icon set, the icon element must have `direction: ltr` (Material Symbols sets this itself) for the icons to keep their positions in a right-to-left context.
66
66
 
67
- - **Prefix**: A prefix (e.g., "$", "NOK") can be included to provide additional context. You can customize the spacing by overriding CSS variables:
67
+ - **Prefix**: A prefix (e.g., "$", "NOK") can be included to provide additional context. You can customize the spacing by overriding CSS variables on the text field element:
68
68
  ```HTML
69
- <span class="micl-textfield__prefix" style="--md-sys-textfield-prefix-space:20px">USD</span>
69
+ <div class="micl-textfield-filled" style="--md-comp-text-field-prefix-space:20px">
70
+ ...
71
+ <span class="micl-textfield__prefix">USD</span>
72
+ ...
73
+ </div>
70
74
  ```
71
75
 
72
76
  ### Trailing Content
@@ -74,9 +78,13 @@ The data-input element may be followed by a trailing text or other element:
74
78
 
75
79
  - **Icon**: Use `micl-textfield__icon-trailing` with a (Material Symbols) icon.
76
80
 
77
- - **Suffix**: A suffix (e.g., "kg", "@gmail.com") can be included to provide additional context. You can customize the spacing by overriding CSS variables:
81
+ - **Suffix**: A suffix (e.g., "kg", "@gmail.com") can be included to provide additional context. You can customize the spacing by overriding CSS variables on the text field element:
78
82
  ```HTML
79
- <span class="micl-textfield__suffix" style="--md-sys-textfield-suffix-space:10em">@gmail.com</span>
83
+ <div class="micl-textfield-outlined" style="--md-comp-text-field-suffix-space:10em">
84
+ ...
85
+ <span class="micl-textfield__suffix">@gmail.com</span>
86
+ ...
87
+ </div>
80
88
  ```
81
89
 
82
90
  ### Supporting Content
@@ -103,6 +111,41 @@ Add a value to the `rows` attribute of the `<textarea>` element to create a text
103
111
  </div>
104
112
  ```
105
113
 
114
+ ## Theming
115
+ Each text field 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 text fields.
116
+
117
+ | Custom property | Meaning | Default |
118
+ |---|---|---|
119
+ | `--md-comp-text-field-container-height` | The height of the text field (excluding supporting text) | `56px` |
120
+ | `--md-comp-text-field-icon-size` | The size of the leading and trailing icons | `24px` |
121
+ | `--md-comp-text-field-icon-space` | The spacing between an icon and the text field's edge | `12px` |
122
+ | `--md-comp-text-field-input-space` | The inline padding around the input text | `16px` |
123
+ | `--md-comp-text-field-prefix-space` | The width reserved for the prefix | `1em` |
124
+ | `--md-comp-text-field-suffix-space` | The width reserved for the suffix | `1em` |
125
+ | `--md-comp-text-field-input-color` | The text color of the input text | `--md-sys-color-on-surface` |
126
+ | `--md-comp-text-field-input-placeholder-color` | The text color of the placeholder | `--md-sys-color-on-surface-variant` |
127
+ | `--md-comp-text-field-caret-color` | The color of the text cursor | `--md-sys-color-primary` |
128
+ | `--md-comp-text-field-label-color` | The text color of the label | `--md-sys-color-on-surface-variant` |
129
+ | `--md-comp-text-field-focus-label-color` | The text color of the label when focused | `--md-sys-color-primary` |
130
+ | `--md-comp-text-field-supporting-text-color` | The text color of the supporting text and character counter | `--md-sys-color-on-surface-variant` |
131
+ | `--md-comp-text-field-icon-color` | The color of the leading and trailing icons | `--md-sys-color-on-surface-variant` |
132
+ | `--md-comp-filled-text-field-container-color` | The background color of a filled text field | `--md-sys-color-surface-container-highest` |
133
+ | `--md-comp-filled-text-field-active-indicator-color` | The bottom line color of a filled text field | `--md-sys-color-on-surface-variant` |
134
+ | `--md-comp-filled-text-field-focus-active-indicator-color` | The bottom line color of a filled text field when focused | `--md-sys-color-primary` |
135
+ | `--md-comp-outlined-text-field-outline-color` | The outline color of an outlined text field | `--md-sys-color-outline` |
136
+ | `--md-comp-outlined-text-field-focus-outline-color` | The outline color of an outlined text field when focused | `--md-sys-color-primary` |
137
+
138
+ **Example: Compact text fields with a brand-colored focus indicator**
139
+
140
+ ```HTML
141
+ <form style="--md-comp-text-field-container-height:48px;--md-comp-outlined-text-field-focus-outline-color:var(--md-sys-color-tertiary)">
142
+ <div class="micl-textfield-outlined">
143
+ <label for="myfield">Label text</label>
144
+ <input type="text" id="myfield">
145
+ </div>
146
+ </form>
147
+ ```
148
+
106
149
  ## Compatibility
107
150
  This component uses relative RGB colors, which might not be supported in your browser. Please check [Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#browser_compatibility) for details.
108
151