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,7 +19,6 @@
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';
@@ -34,22 +33,31 @@
34
33
  @include typography.scale('body-large');
35
34
  @include typography.scale('body-small');
36
35
 
37
- .micl-textfield-filled,
38
- .micl-textfield-outlined {
39
- --md-sys-textfield-height: 56px;
40
- --md-sys-textfield-icon-size: 24px;
41
- --md-sys-textfield-icon-space: 12px;
42
- --md-sys-textfield-input-space: 16px;
43
- --md-sys-textfield-prefix-space: 1em;
44
- --md-sys-textfield-suffix-space: 1em;
45
- --md-sys-textfield-motion-effects: #{motion.$md-sys-motion-expressive-slow-effects};
46
- --md-sys-textfield-motion-duration: #{motion.$md-sys-motion-expressive-slow-effects-duration};
47
- --md-sys-textfield-motion-duration-reverse: #{motion.$md-sys-motion-expressive-default-effects-duration};
36
+ $textfields: ':is(.micl-textfield-filled, .micl-textfield-outlined)';
37
+ $fields: ':is(input, select, textarea)';
38
+
39
+ // A text field is "populated" when its label floats.
40
+ $populated: ':has(> :focus, > [data-miclvalue], > :is([type=date], [type=datetime-local], [type=month], [type=time], [type=week]), > input[value]:not([value=""], [data-miclinitialized]), > select:not([data-miclinitialized]) option:checked:not([value=""]), > textarea:not(:empty, [data-miclinitialized]))';
41
+
42
+ #{$textfields} {
43
+ --_height: var(--md-comp-text-field-container-height, 56px);
44
+ --_shape: var(--md-sys-shape-corner-extra-small);
45
+ --_icon-size: var(--md-comp-text-field-icon-size, 24px);
46
+ --_icon-space: var(--md-comp-text-field-icon-space, 12px);
47
+ --_input-space: var(--md-comp-text-field-input-space, 16px);
48
+ --_icon-leading: 0px;
49
+ --_icon-trailing: 0px;
50
+ --_prefix: 0px;
51
+ --_suffix: 0px;
52
+ --_outline-width: 1px;
53
+ --_label-color: var(--md-comp-text-field-label-color, var(--md-sys-color-on-surface-variant));
54
+ --_effects: var(--md-comp-text-field-motion-effects, #{motion.$md-sys-motion-expressive-slow-effects});
55
+ --_duration: var(--md-comp-text-field-motion-duration, #{motion.$md-sys-motion-expressive-slow-effects-duration});
56
+ --_duration-reverse: var(--md-comp-text-field-motion-duration-reverse, #{motion.$md-sys-motion-expressive-default-effects-duration});
48
57
 
49
58
  display: grid;
50
59
  grid-template-areas: "textfield" "supporting";
51
60
  align-items: center;
52
- background-color: inherit;
53
61
 
54
62
  &> label {
55
63
  @include typography.body-large;
@@ -59,42 +67,40 @@
59
67
  align-self: flex-start;
60
68
  width: fit-content;
61
69
  padding-inline: 4px;
62
- margin-block-start: calc((var(--md-sys-textfield-height) - var(--md-sys-typescale-body-large-line-height)) / 2);
63
- margin-inline: 12px 4px;
64
- border-radius: 4px;
65
- background-color: var(--_dialog-background-color, var(--_card-background-color, inherit));
66
- color: var(--md-sys-color-on-surface-variant);
70
+ margin-block-start: calc((var(--_height) - var(--md-sys-typescale-body-large-line-height)) / 2);
71
+ color: var(--_label-color);
67
72
  z-index: 1;
68
73
  transition:
69
- margin-block-start var(--md-sys-textfield-motion-duration) var(--md-sys-textfield-motion-effects),
70
- margin-inline-start var(--md-sys-textfield-motion-duration) var(--md-sys-textfield-motion-effects),
71
- font-size var(--md-sys-textfield-motion-duration) linear,
72
- letter-spacing var(--md-sys-textfield-motion-duration) linear;
74
+ margin var(--_duration) var(--_effects),
75
+ font-size var(--_duration) linear,
76
+ letter-spacing var(--_duration) linear;
73
77
  }
74
- &> input,
75
- &> select,
76
- &> textarea {
78
+ &> #{$fields} {
77
79
  @include typography.body-large;
78
80
 
79
81
  box-sizing: border-box;
80
82
  grid-area: textfield;
81
83
  margin: 0;
82
- padding-inline: var(--md-sys-textfield-input-space);
84
+ padding-inline:
85
+ calc(var(--_input-space) - var(--_border, 0px) + var(--_icon-leading) + var(--_prefix))
86
+ calc(var(--_input-space) - var(--_border, 0px) + var(--_icon-trailing) + var(--_suffix));
83
87
  border: none;
84
- border-block-end: 1px solid var(--md-sys-color-on-surface-variant);
85
- border-radius: var(--md-sys-shape-corner-extra-small);
88
+ border-radius: var(--_shape);
86
89
  outline: none;
87
- color: var(--md-sys-color-on-surface);
90
+ color: var(--md-comp-text-field-input-color, var(--md-sys-color-on-surface));
88
91
  background-color: transparent;
89
92
  text-overflow: ellipsis;
90
- caret-color: var(--md-sys-color-primary);
93
+ caret-color: var(--_caret-color, var(--md-comp-text-field-caret-color, var(--md-sys-color-primary)));
91
94
 
92
95
  &:disabled {
93
- border-block-end-color: rgb(from var(--md-sys-color-on-surface) r g b / var(--md-sys-state-disabled-state-layer-opacity, 38%));
94
96
  color: rgb(from var(--md-sys-color-on-surface) r g b / var(--md-sys-state-disabled-state-layer-opacity, 38%));
97
+
98
+ &::placeholder {
99
+ color: rgb(from var(--md-sys-color-on-surface) r g b / var(--md-sys-state-disabled-state-layer-opacity, 38%));
100
+ }
95
101
  }
96
102
  &::placeholder {
97
- color: var(--md-sys-color-on-surface-variant);
103
+ color: var(--md-comp-text-field-input-placeholder-color, var(--md-sys-color-on-surface-variant));
98
104
  }
99
105
  &::-webkit-inner-spin-button,
100
106
  &::-webkit-outer-spin-button {
@@ -105,14 +111,13 @@
105
111
  -moz-appearance: textfield;
106
112
  }
107
113
  }
108
- &> input,
109
- &> select {
110
- height: var(--md-sys-textfield-height);
114
+ &> :is(input, select) {
115
+ height: var(--_height);
111
116
  padding-block: 0;
112
117
  }
113
118
  &> textarea {
114
- min-height: var(--md-sys-textfield-height);
115
- padding-block: calc((var(--md-sys-textfield-height) - var(--md-sys-typescale-body-large-line-height)) / 2);
119
+ min-height: var(--_height);
120
+ padding-block: calc((var(--_height) - var(--md-sys-typescale-body-large-line-height)) / 2);
116
121
  resize: none;
117
122
 
118
123
  &[rows] {
@@ -130,70 +135,59 @@
130
135
 
131
136
  grid-area: textfield;
132
137
  align-content: center;
133
- height: var(--md-sys-textfield-height);
138
+ height: var(--_height);
134
139
  color: var(--md-sys-color-on-surface-variant);
135
140
  opacity: 0;
136
141
  z-index: 1;
137
- transition: opacity var(--md-sys-textfield-motion-duration-reverse) linear;
142
+ transition: opacity var(--_duration-reverse) linear;
138
143
  }
139
144
  &> .micl-textfield__prefix {
140
- width: var(--md-sys-textfield-prefix-space);
141
- padding-inline-start: var(--md-sys-textfield-input-space);
145
+ width: var(--md-comp-text-field-prefix-space, 1em);
146
+ padding-inline-start: calc(var(--_input-space) + var(--_icon-leading));
142
147
  }
143
148
  &> .micl-textfield__suffix {
144
- width: var(--md-sys-textfield-suffix-space);
145
- padding-inline-end: var(--md-sys-textfield-input-space);
149
+ width: var(--md-comp-text-field-suffix-space, 1em);
150
+ padding-inline-end: calc(var(--_input-space) + var(--_icon-trailing));
146
151
  margin-inline: auto 0;
147
152
  }
148
153
  &> .micl-textfield__icon-leading,
149
154
  &> .micl-textfield__icon-trailing {
150
155
  grid-area: textfield;
151
156
  width: 1em;
152
- margin-inline: var(--md-sys-textfield-icon-space) auto;
153
- font-size: var(--md-sys-textfield-icon-size);
154
- color: var(--md-sys-color-on-surface-variant);
157
+ margin-inline: var(--_icon-space) auto;
158
+ font-size: var(--_icon-size);
159
+ color: var(--md-comp-text-field-icon-color, var(--md-sys-color-on-surface-variant));
155
160
  z-index: 1;
156
161
  }
157
162
  &> .micl-textfield__icon-trailing {
158
- margin-inline: auto var(--md-sys-textfield-icon-space);
163
+ margin-inline: auto var(--_icon-space);
159
164
  }
165
+
160
166
  &:has(> .micl-textfield__prefix) {
161
- &> input,
162
- &> textarea {
163
- padding-inline-start: calc(var(--md-sys-textfield-input-space) + var(--md-sys-textfield-prefix-space));
164
- }
167
+ --_prefix: var(--md-comp-text-field-prefix-space, 1em);
165
168
  }
166
169
  &:has(> .micl-textfield__suffix) {
167
- &> input,
168
- &> textarea {
169
- padding-inline-end: calc(var(--md-sys-textfield-suffix-space) + var(--md-sys-textfield-input-space));
170
- }
170
+ --_suffix: var(--md-comp-text-field-suffix-space, 1em);
171
171
  }
172
172
  &:has(> .micl-textfield__icon-leading) {
173
- &> label {
174
- margin-inline-start: calc(var(--md-sys-textfield-icon-space) + var(--md-sys-textfield-icon-size) + var(--md-sys-textfield-input-space));
175
- }
176
- &> .micl-textfield__prefix,
177
- &> input,
178
- &> textarea {
179
- padding-inline-start: calc(var(--md-sys-textfield-icon-space) + var(--md-sys-textfield-icon-size) + var(--md-sys-textfield-input-space));
180
- }
181
- &:has(> .micl-textfield__prefix) > input,
182
- &:has(> .micl-textfield__prefix) > textarea {
183
- padding-inline-start: calc(var(--md-sys-textfield-input-space) + var(--md-sys-textfield-icon-size) + var(--md-sys-textfield-icon-space) + var(--md-sys-textfield-prefix-space));
184
- }
173
+ --_icon-leading: calc(var(--_icon-size) + var(--_icon-space));
185
174
  }
186
175
  &:has(> .micl-textfield__icon-trailing) {
187
- &> .micl-textfield__suffix,
188
- &> input,
189
- &> textarea {
190
- padding-inline-end: calc(var(--md-sys-textfield-input-space) + var(--md-sys-textfield-icon-size) + var(--md-sys-textfield-icon-space));
176
+ --_icon-trailing: calc(var(--_icon-size) + var(--_icon-space));
177
+ }
178
+
179
+ // While the label rests on top of the data element, hide the text that would shine
180
+ // through it: the input placeholder and the label of a selected empty-value option.
181
+ // A focused or populated text field moves the label out of the way and both return.
182
+ &:has(> label):not(#{$populated}) {
183
+ &> select {
184
+ color: transparent;
191
185
  }
192
- &:has(> .micl-textfield__suffix) > input,
193
- &:has(> .micl-textfield__suffix) > textarea {
194
- padding-inline-end: calc(var(--md-sys-textfield-input-space) + var(--md-sys-textfield-icon-size) + var(--md-sys-textfield-prefix-space) + var(--md-sys-textfield-icon-space));
186
+ &> #{$fields}::placeholder {
187
+ color: transparent;
195
188
  }
196
189
  }
190
+
197
191
  &> .micl-textfield__supporting-text,
198
192
  &> .micl-textfield__character-counter {
199
193
  @include typography.body-small;
@@ -201,252 +195,202 @@
201
195
  grid-area: supporting;
202
196
  padding-block: 4px 0;
203
197
  padding-inline: 16px;
204
- color: var(--md-sys-color-on-surface-variant);
205
-
206
- &.micl-textfield__supporting-text--focus {
207
- visibility: hidden;
208
- }
198
+ color: var(--md-comp-text-field-supporting-text-color, var(--md-sys-color-on-surface-variant));
199
+ }
200
+ &> .micl-textfield__supporting-text--focus {
201
+ visibility: hidden;
209
202
  }
210
203
  &> .micl-textfield__character-counter {
211
204
  justify-self: flex-end;
212
205
  }
213
- &:has(> input:active),
214
- &:has(> select:active),
215
- &:has(> textarea:active),
216
- &:has(> input:focus),
217
- &:has(> select:focus),
218
- &:has(> textarea:focus),
219
- &:has(> input:focus-visible),
220
- &:has(> select:focus-visible),
221
- &:has(> textarea:focus-visible) {
222
- &> label {
223
- color: var(--md-sys-color-primary);
224
- }
225
- &> .micl-textfield__supporting-text.micl-textfield__supporting-text--focus {
226
- visibility: visible;
227
- }
228
- }
229
- &:has(> input:disabled),
230
- &:has(> select:disabled),
231
- &:has(> textarea:disabled) {
232
- &> label {
233
- color: rgb(from var(--md-sys-color-on-surface) r g b / var(--md-sys-state-disabled-state-layer-opacity, 38%));
234
- }
235
- &> .micl-textfield__icon-leading,
236
- &> .micl-textfield__icon-trailing,
237
- &> .micl-textfield__supporting-text {
238
- color: rgb(from var(--md-sys-color-on-surface) r g b / var(--md-sys-state-disabled-state-layer-opacity, 38%));
239
- }
240
- &> .micl-textfield__character-counter {
241
- display: none;
242
- }
243
- }
244
- &:has(> input:not([maxlength])),
245
- &:has(> textarea:not([maxlength])) {
246
- &> .micl-textfield__character-counter {
247
- display: none;
248
- }
206
+ &:has(> :is(input, textarea):not([maxlength]), > select) > .micl-textfield__character-counter {
207
+ display: none;
249
208
  }
250
- &:has(> input[maxlength]:not(:disabled)):has(> .micl-textfield__character-counter),
251
- &:has(> textarea[maxlength]:not(:disabled)):has(> .micl-textfield__character-counter) {
252
- &> .micl-textfield__supporting-text {
253
- padding-inline-end: 64px;
254
- }
209
+ &:has(> :is(input, textarea)[maxlength]:not(:disabled)):has(> .micl-textfield__character-counter) > .micl-textfield__supporting-text {
210
+ padding-inline-end: 64px;
255
211
  }
256
212
  }
257
213
 
258
214
  .micl-textfield-filled {
215
+ --_outline-color: var(--md-comp-filled-text-field-active-indicator-color, var(--md-sys-color-on-surface-variant));
216
+ --_focus-outline-color: var(--md-comp-filled-text-field-focus-active-indicator-color, var(--md-sys-color-primary));
217
+
259
218
  &> label {
260
- background-color: transparent;
219
+ margin-inline: 12px 4px;
261
220
  }
262
- &:hover {
263
- &> input:not(:disabled),
264
- &> select:not(:disabled),
265
- &> textarea:not(:disabled) {
266
- --statelayer-opacity: var(--md-sys-state-hover-state-layer-opacity, 8%);
267
-
268
- border-block-end-color: var(--md-sys-color-on-surface);
269
- }
221
+ &:hover > #{$fields}:not(:disabled) {
222
+ --statelayer-opacity: var(--md-sys-state-hover-state-layer-opacity, 8%);
270
223
  }
271
- &> input,
272
- &> select,
273
- &> textarea {
224
+ &> #{$fields} {
274
225
  --statelayer-color: var(--md-sys-color-on-surface);
275
226
 
276
227
  padding-block-start: 18px;
277
- padding-block-end: 2px;
228
+ padding-block-end: calc(3px - var(--_outline-width));
229
+ border-block-end: var(--_outline-width) solid var(--_outline-color);
278
230
  border-end-start-radius: 0;
279
231
  border-end-end-radius: 0;
280
- outline: none;
281
- background-color: var(--md-sys-color-surface-container-highest);
232
+ background-color: var(--md-comp-filled-text-field-container-color, var(--md-sys-color-surface-container-highest));
282
233
  background-image: linear-gradient(rgb(from var(--statelayer-color) r g b / var(--statelayer-opacity)));
283
234
  background-repeat: no-repeat;
284
- transition: --statelayer-opacity var(--md-sys-textfield-motion-duration) linear;
235
+ transition: --statelayer-opacity var(--_duration) linear;
285
236
 
286
237
  &:disabled {
287
238
  background-color: rgb(from var(--md-sys-color-on-surface) r g b / 4%);
288
239
  }
289
- &:not(:disabled):focus,
290
- &:not(:disabled):focus-visible,
291
- &:not(:disabled):active {
292
- padding-block-end: 0px;
293
- border-block-end-width: 3px;
294
- border-block-end-color: var(--md-sys-color-primary);
295
- }
296
- }
297
- &> input {
298
- width: 100%;
299
240
  }
300
241
  &> textarea {
301
242
  padding-block-start: 24px;
302
243
  }
303
- &:has(
304
- > input:focus,
305
- > input[value]:not([value='']):not([data-miclinitialized]),
306
- > input[data-miclvalue],
307
- > input[type=date],
308
- > input[type=datetime-local],
309
- > input[type=month],
310
- > input[type=time],
311
- > input[type=week],
312
- > select:focus,
313
- > select:not([data-miclinitialized]) option:checked:not([value='']),
314
- > select[data-miclvalue],
315
- > textarea:focus,
316
- > textarea:not(:empty):not([data-miclinitialized]),
317
- > textarea[data-miclvalue]
318
- ) {
244
+ &:has(> .micl-textfield__icon-leading) > label {
245
+ margin-inline-start: calc(var(--_input-space) + var(--_icon-leading));
246
+ }
247
+ &#{$populated} {
319
248
  &> label {
320
- @include typography.body-small;
321
-
322
249
  margin-block-start: 8px;
323
250
  margin-inline-start: 12px;
324
251
  }
325
252
  &:has(> .micl-textfield__icon-leading) > label {
326
- margin-inline-start: calc(var(--md-sys-textfield-input-space) + var(--md-sys-textfield-icon-size) + var(--md-sys-textfield-icon-space) - 4px);
253
+ margin-inline-start: calc(var(--_input-space) + var(--_icon-leading) - 4px);
327
254
  }
328
255
  &> .micl-textfield__prefix,
329
256
  &> .micl-textfield__suffix {
330
257
  height: 40px;
331
258
  margin-block-start: 16px;
332
- opacity: 1;
333
259
  }
334
260
  }
335
261
  }
262
+
336
263
  .micl-textfield-outlined {
337
- margin-block-start: calc(2px + var(--md-sys-typescale-body-small-line-height)/2);
264
+ --_outline-color: var(--md-comp-outlined-text-field-outline-color, var(--md-sys-color-outline));
265
+ --_focus-outline-color: var(--md-comp-outlined-text-field-focus-outline-color, var(--md-sys-color-primary));
266
+ --_disabled-outline-opacity: 12%;
267
+ --_border: var(--_outline-width);
268
+ --_outline-extra: calc(var(--_outline-width) - 1px);
269
+
270
+ grid-template:
271
+ "textfield textfield textfield"
272
+ "supporting supporting supporting"
273
+ / 12px fit-content(calc(100% - 24px)) 1fr;
274
+ margin-block-start: calc(2px + var(--md-sys-typescale-body-small-line-height) / 2);
338
275
 
276
+ // The outline's top edge is drawn by these two pseudo-elements. The label sits in the
277
+ // middle grid column, so the notch for a floating label opens by retracting ::before
278
+ // to the first column.
279
+ &::before,
280
+ &::after {
281
+ content: '';
282
+ grid-area: textfield;
283
+ align-self: start;
284
+ height: var(--_shape);
285
+ border-block-start: var(--_outline-width) solid var(--_outline-color);
286
+ }
287
+ &::before {
288
+ grid-column: 1 / 3;
289
+ border-start-start-radius: var(--_shape);
290
+ }
291
+ &::after {
292
+ grid-column: 3;
293
+ border-start-end-radius: var(--_shape);
294
+ }
339
295
  &:hover {
340
- &> label {
341
- color: var(--md-sys-color-on-surface);
342
- }
343
- &> input:not(:disabled),
344
- &> select:not(:disabled),
345
- &> textarea:not(:disabled) {
346
- outline-color: var(--md-sys-color-on-surface);
347
- color: var(--md-sys-color-on-surface);
348
- }
296
+ --_label-color: var(--md-sys-color-on-surface);
297
+ }
298
+ &> label {
299
+ grid-column: 2;
300
+ }
301
+ &:has(> .micl-textfield__icon-leading) > label {
302
+ margin-inline-start: calc(var(--_input-space) + var(--_icon-leading) - 12px);
349
303
  }
350
- &> input,
351
- &> select,
304
+ &> #{$fields} {
305
+ border-block-end: var(--_border) solid var(--_outline-color);
306
+ border-inline: var(--_border) solid var(--_outline-color);
307
+ }
308
+
309
+ &> input {
310
+ padding-block-start: calc(var(--_border) - 1px);
311
+ }
312
+
352
313
  &> textarea {
353
- margin: 0px 3px 3px 3px;
354
- border: none;
355
- outline: 1px solid var(--md-sys-color-outline);
314
+ --_border: 1px;
356
315
 
357
- &:disabled {
358
- outline-color: rgb(from var(--md-sys-color-on-surface) r g b / 12%);
316
+ box-shadow:
317
+ inset var(--_outline-extra) 0 var(--_outline-color),
318
+ inset calc(0px - var(--_outline-extra)) 0 var(--_outline-color),
319
+ inset 0 calc(0px - var(--_outline-extra)) var(--_outline-color);
320
+ }
321
+ &#{$populated} {
322
+ &::before {
323
+ grid-column: 1;
359
324
  }
360
- &:not(:disabled):focus,
361
- &:not(:disabled):focus-visible,
362
- &:not(:disabled):active {
363
- outline-width: 3px;
364
- outline-color: var(--md-sys-color-primary);
325
+ &> label {
326
+ margin-block-start: calc(-2px - var(--md-sys-typescale-body-small-line-height) / 2);
327
+ margin-inline-start: 0;
365
328
  }
366
329
  }
367
- &> input {
368
- width: calc(100% - 3px - 3px);
369
- }
370
- &:has(
371
- > input:focus,
372
- > input[value]:not([value='']):not([data-miclinitialized]),
373
- > input[data-miclvalue],
374
- > input[type=date],
375
- > input[type=datetime-local],
376
- > input[type=month],
377
- > input[type=time],
378
- > input[type=week],
379
- > select:focus,
380
- > select:not([data-miclinitialized]) option:checked:not([value='']),
381
- > select[data-miclvalue],
382
- > textarea:focus,
383
- > textarea:not(:empty):not([data-miclinitialized]),
384
- > textarea[data-miclvalue]
385
- ) {
330
+ }
331
+
332
+ // Shared states. Rule order matters here — focus must follow hover, the disabled overrides must come last.
333
+ #{$textfields} {
334
+ &:hover {
335
+ --_outline-color: var(--md-sys-color-on-surface);
336
+ }
337
+ &:has(> :focus) {
338
+ --_outline-width: 3px;
339
+ --_outline-color: var(--_focus-outline-color);
340
+ --_label-color: var(--md-comp-text-field-focus-label-color, var(--md-sys-color-primary));
341
+
342
+ &> .micl-textfield__supporting-text--focus {
343
+ visibility: visible;
344
+ }
345
+ }
346
+ &#{$populated} {
386
347
  &> label {
387
348
  @include typography.body-small;
388
-
389
- margin-block-start: calc(-2px - var(--md-sys-typescale-body-small-line-height) / 2);
390
- margin-inline-start: 12px;
391
349
  }
392
350
  &> .micl-textfield__prefix,
393
351
  &> .micl-textfield__suffix {
394
352
  opacity: 1;
395
353
  }
396
354
  }
355
+ &:has(> :disabled) {
356
+ --_outline-color: rgb(from var(--md-sys-color-on-surface) r g b / var(--_disabled-outline-opacity, 38%));
357
+
358
+ &> :is(label, [class*=micl-textfield__]:not(.micl-textfield__character-counter)) {
359
+ color: rgb(from var(--md-sys-color-on-surface) r g b / var(--md-sys-state-disabled-state-layer-opacity, 38%));
360
+ }
361
+ &> .micl-textfield__character-counter {
362
+ display: none;
363
+ }
364
+ }
397
365
  }
398
366
 
399
- .micl-textfield-filled.micl-textfield--error,
400
- .micl-textfield-outlined.micl-textfield--error {
401
- &> label,
367
+ .micl-textfield--error:not(:has(> :disabled)) {
368
+ --_outline-color: var(--md-sys-color-error);
369
+ --_caret-color: var(--md-sys-color-error);
370
+ --_label-color: var(--md-sys-color-error);
371
+
402
372
  &> .micl-textfield__icon-trailing,
403
373
  &> .micl-textfield__supporting-text,
404
374
  &> .micl-textfield__character-counter {
405
375
  color: var(--md-sys-color-error);
406
376
  }
407
- &> input,
408
- &> textarea {
409
- border-block-end-color: var(--md-sys-color-error);
410
- outline-color: var(--md-sys-color-error);
411
- caret-color: var(--md-sys-color-error);
412
-
413
- &:active,
414
- &:focus,
415
- &:focus-visible {
416
- border-block-end-color: var(--md-sys-color-error);
417
- outline-color: var(--md-sys-color-error);
418
- }
419
- }
420
- &:hover {
421
- &> label,
377
+ &:hover:not(:has(> :focus)) {
378
+ --_outline-color: var(--md-sys-color-on-error-container);
379
+ --_label-color: var(--md-sys-color-on-error-container);
380
+
422
381
  &> .micl-textfield__icon-trailing {
423
382
  color: var(--md-sys-color-on-error-container);
424
383
  }
425
- &> input,
426
- &> textarea {
427
- border-block-end-color: var(--md-sys-color-on-error-container);
428
- outline-color: var(--md-sys-color-on-error-container);
429
- }
430
- }
431
- &:has(> input:active),
432
- &:has(> input:focus),
433
- &:has(> input:focus-visible),
434
- &:has(> textarea:active),
435
- &:has(> textarea:focus),
436
- &:has(> textarea:focus-visible) {
437
- &> label,
438
- &> .micl-textfield__icon-trailing {
439
- color: var(--md-sys-color-error);
440
- }
441
384
  }
442
385
  }
443
386
 
444
- [dir=rtl] .micl-textfield-filled,
445
- [dir=rtl] .micl-textfield-outlined {
387
+ // If the icon elements are direction:ltr (like Material Symbols), their margin-inline resolves
388
+ // against ltr and does not flip with the page direction — mirror them explicitly.
389
+ #{$textfields}:dir(rtl) {
446
390
  &> .micl-textfield__icon-leading {
447
- margin-inline: auto var(--md-sys-textfield-icon-space);
391
+ margin-inline: auto var(--_icon-space);
448
392
  }
449
393
  &> .micl-textfield__icon-trailing {
450
- margin-inline: var(--md-sys-textfield-icon-space) auto;
394
+ margin-inline: var(--_icon-space) auto;
451
395
  }
452
396
  }