material-inspired-component-library 8.1.1 → 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 (283) 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 +7 -5
  13. package/components/button/_shared.scss +210 -0
  14. package/components/button/index.scss +49 -283
  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 +8 -3
  29. package/components/iconbutton/index.scss +83 -186
  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 +60 -36
  37. package/components/navigationrail/_navitem.scss +96 -0
  38. package/components/navigationrail/index.scss +76 -130
  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/iconbutton/index.d.ts +2 -7
  80. package/dist/components/slider/index.d.ts +1 -1
  81. package/dist/components/textfield/index.d.ts +2 -2
  82. package/dist/datepicker.css +1 -1
  83. package/dist/datepicker.js +1 -1
  84. package/dist/dialog.css +1 -1
  85. package/dist/dialog.js +1 -1
  86. package/dist/divider.css +1 -1
  87. package/dist/divider.js +1 -1
  88. package/dist/field.css +1 -0
  89. package/dist/field.js +1 -0
  90. package/dist/foundations/form/index.js +1 -1
  91. package/dist/foundations/runtime.d.ts +15 -0
  92. package/dist/foundations/runtime.js +1 -0
  93. package/dist/iconbutton.css +1 -1
  94. package/dist/iconbutton.js +1 -1
  95. package/dist/layout.css +1 -1
  96. package/dist/layout.js +1 -1
  97. package/dist/list.css +1 -1
  98. package/dist/list.js +1 -1
  99. package/dist/menu.css +1 -1
  100. package/dist/menu.js +1 -1
  101. package/dist/micl.css +1 -1
  102. package/dist/micl.d.ts +14 -5
  103. package/dist/micl.js +1 -1
  104. package/dist/navigationbar.css +1 -0
  105. package/dist/navigationbar.js +1 -0
  106. package/dist/navigationrail.css +1 -1
  107. package/dist/navigationrail.js +1 -1
  108. package/dist/progressindicator.css +1 -1
  109. package/dist/progressindicator.js +1 -1
  110. package/dist/radio.css +1 -1
  111. package/dist/radio.js +1 -1
  112. package/dist/scrollbar.js +1 -1
  113. package/dist/select.css +1 -1
  114. package/dist/select.js +1 -1
  115. package/dist/shapes.css +1 -1
  116. package/dist/shapes.js +1 -1
  117. package/dist/sidesheet.css +1 -1
  118. package/dist/sidesheet.js +1 -1
  119. package/dist/slider.css +1 -1
  120. package/dist/slider.js +1 -1
  121. package/dist/snackbar.css +1 -1
  122. package/dist/snackbar.js +1 -1
  123. package/dist/stepper.css +1 -1
  124. package/dist/stepper.js +1 -1
  125. package/dist/switch.css +1 -1
  126. package/dist/switch.js +1 -1
  127. package/dist/textfield.css +1 -1
  128. package/dist/textfield.js +1 -1
  129. package/dist/timepicker.css +1 -1
  130. package/dist/timepicker.js +1 -1
  131. package/foundations/_index.scss +35 -0
  132. package/foundations/{index.scss → base/index.scss} +21 -56
  133. package/foundations/field/index.scss +37 -0
  134. package/foundations/layout/index.scss +64 -65
  135. package/package.json +23 -9
  136. package/styles/statelayer.scss +20 -5
  137. package/styles.scss +5 -2
  138. package/.claude/settings.local.json +0 -17
  139. package/.editorconfig +0 -12
  140. package/.gitattributes +0 -9
  141. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -35
  142. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  143. package/CLAUDE.md +0 -53
  144. package/CODE_OF_CONDUCT.md +0 -128
  145. package/components/bottomsheet/index.ts +0 -153
  146. package/components/button/index.ts +0 -79
  147. package/components/checkbox/index.ts +0 -148
  148. package/components/datepicker/index.ts +0 -693
  149. package/components/iconbutton/index.ts +0 -77
  150. package/components/list/index.ts +0 -138
  151. package/components/menu/index.ts +0 -145
  152. package/components/navigationrail/index.ts +0 -87
  153. package/components/progressindicator/index.ts +0 -77
  154. package/components/slider/index.ts +0 -149
  155. package/components/snackbar/index.ts +0 -118
  156. package/components/stepper/index.ts +0 -248
  157. package/components/textfield/index.ts +0 -188
  158. package/components/timepicker/index.ts +0 -413
  159. package/dist/components/progressindicator/index.d.ts +0 -6
  160. package/dist/foundations.css +0 -1
  161. package/dist/foundations.js +0 -1
  162. package/docs/accordion.html +0 -344
  163. package/docs/alert.html +0 -177
  164. package/docs/bottomsheet.html +0 -240
  165. package/docs/button.html +0 -291
  166. package/docs/card-awards.webp +0 -0
  167. package/docs/card-cabinet.webp +0 -0
  168. package/docs/card-city.webp +0 -0
  169. package/docs/card-fingerprint.webp +0 -0
  170. package/docs/card-holiday.webp +0 -0
  171. package/docs/card-names.webp +0 -0
  172. package/docs/card.html +0 -159
  173. package/docs/checkbox.html +0 -147
  174. package/docs/datepicker.html +0 -274
  175. package/docs/dialog.html +0 -195
  176. package/docs/divider.html +0 -139
  177. package/docs/docs.css +0 -26
  178. package/docs/docs.js +0 -139
  179. package/docs/iconbutton.html +0 -331
  180. package/docs/index.html +0 -431
  181. package/docs/list.html +0 -310
  182. package/docs/menu.html +0 -574
  183. package/docs/micl.css +0 -1
  184. package/docs/micl.js +0 -1
  185. package/docs/navigationrail.html +0 -138
  186. package/docs/progressindicator.html +0 -288
  187. package/docs/radio.html +0 -123
  188. package/docs/select.html +0 -337
  189. package/docs/shapes.css +0 -1
  190. package/docs/shapes.html +0 -159
  191. package/docs/shapes.js +0 -1
  192. package/docs/sidesheet.html +0 -149
  193. package/docs/slider.html +0 -141
  194. package/docs/snackbar.html +0 -102
  195. package/docs/stepper.html +0 -319
  196. package/docs/switch.html +0 -196
  197. package/docs/textfield.html +0 -208
  198. package/docs/themes/airblue/dark-hc.css +0 -51
  199. package/docs/themes/airblue/dark-mc.css +0 -51
  200. package/docs/themes/airblue/dark.css +0 -51
  201. package/docs/themes/airblue/light-hc.css +0 -51
  202. package/docs/themes/airblue/light-mc.css +0 -51
  203. package/docs/themes/airblue/light.css +0 -51
  204. package/docs/themes/airblue/theme.css +0 -306
  205. package/docs/themes/barnred/dark-hc.css +0 -51
  206. package/docs/themes/barnred/dark-mc.css +0 -51
  207. package/docs/themes/barnred/dark.css +0 -51
  208. package/docs/themes/barnred/light-hc.css +0 -51
  209. package/docs/themes/barnred/light-mc.css +0 -51
  210. package/docs/themes/barnred/light.css +0 -51
  211. package/docs/themes/barnred/theme.css +0 -306
  212. package/docs/themes/citrine/dark-hc.css +0 -51
  213. package/docs/themes/citrine/dark-mc.css +0 -51
  214. package/docs/themes/citrine/dark.css +0 -51
  215. package/docs/themes/citrine/light-hc.css +0 -51
  216. package/docs/themes/citrine/light-mc.css +0 -51
  217. package/docs/themes/citrine/light.css +0 -51
  218. package/docs/themes/citrine/theme.css +0 -306
  219. package/docs/themes/gray/dark-hc.css +0 -51
  220. package/docs/themes/gray/dark-mc.css +0 -51
  221. package/docs/themes/gray/dark.css +0 -51
  222. package/docs/themes/gray/light-hc.css +0 -51
  223. package/docs/themes/gray/light-mc.css +0 -51
  224. package/docs/themes/gray/light.css +0 -51
  225. package/docs/themes/gray/theme.css +0 -306
  226. package/docs/themes/greenery/dark-hc.css +0 -51
  227. package/docs/themes/greenery/dark-mc.css +0 -51
  228. package/docs/themes/greenery/dark.css +0 -51
  229. package/docs/themes/greenery/light-hc.css +0 -51
  230. package/docs/themes/greenery/light-mc.css +0 -51
  231. package/docs/themes/greenery/light.css +0 -51
  232. package/docs/themes/greenery/theme.css +0 -306
  233. package/docs/themes/hermana/dark-hc.css +0 -51
  234. package/docs/themes/hermana/dark-mc.css +0 -51
  235. package/docs/themes/hermana/dark.css +0 -51
  236. package/docs/themes/hermana/light-hc.css +0 -51
  237. package/docs/themes/hermana/light-mc.css +0 -51
  238. package/docs/themes/hermana/light.css +0 -51
  239. package/docs/themes/hermana/theme.css +0 -306
  240. package/docs/themes/illuminating/dark-hc.css +0 -51
  241. package/docs/themes/illuminating/dark-mc.css +0 -51
  242. package/docs/themes/illuminating/dark.css +0 -51
  243. package/docs/themes/illuminating/light-hc.css +0 -51
  244. package/docs/themes/illuminating/light-mc.css +0 -51
  245. package/docs/themes/illuminating/light.css +0 -51
  246. package/docs/themes/illuminating/theme.css +0 -306
  247. package/docs/themes/magenta/dark-hc.css +0 -51
  248. package/docs/themes/magenta/dark-mc.css +0 -51
  249. package/docs/themes/magenta/dark.css +0 -51
  250. package/docs/themes/magenta/light-hc.css +0 -51
  251. package/docs/themes/magenta/light-mc.css +0 -51
  252. package/docs/themes/magenta/light.css +0 -51
  253. package/docs/themes/magenta/theme.css +0 -306
  254. package/docs/themes/mocha/dark-hc.css +0 -51
  255. package/docs/themes/mocha/dark-mc.css +0 -51
  256. package/docs/themes/mocha/dark.css +0 -51
  257. package/docs/themes/mocha/light-hc.css +0 -51
  258. package/docs/themes/mocha/light-mc.css +0 -51
  259. package/docs/themes/mocha/light.css +0 -51
  260. package/docs/themes/mocha/theme.css +0 -306
  261. package/docs/themes/olivegreen/dark-hc.css +0 -51
  262. package/docs/themes/olivegreen/dark-mc.css +0 -51
  263. package/docs/themes/olivegreen/dark.css +0 -51
  264. package/docs/themes/olivegreen/light-hc.css +0 -51
  265. package/docs/themes/olivegreen/light-mc.css +0 -51
  266. package/docs/themes/olivegreen/light.css +0 -51
  267. package/docs/themes/olivegreen/theme.css +0 -306
  268. package/docs/themes/peri/dark-hc.css +0 -51
  269. package/docs/themes/peri/dark-mc.css +0 -51
  270. package/docs/themes/peri/dark.css +0 -51
  271. package/docs/themes/peri/light-hc.css +0 -51
  272. package/docs/themes/peri/light-mc.css +0 -51
  273. package/docs/themes/peri/light.css +0 -51
  274. package/docs/themes/peri/theme.css +0 -306
  275. package/docs/timepicker.html +0 -160
  276. package/foundations/form/index.ts +0 -174
  277. package/foundations/layout/README.md +0 -127
  278. package/intl.d.ts +0 -9
  279. package/micl.ts +0 -221
  280. package/styles/README.md +0 -196
  281. package/tools/shapes/generate.mjs +0 -828
  282. package/tsconfig.json +0 -116
  283. package/webpack.config.js +0 -159
@@ -0,0 +1,210 @@
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
+ // The shared foundation of the Button component: the state selectors and the
23
+ // %micl-button-* placeholders, which the Chip component extends as well.
24
+
25
+ @use '../../styles/elevation';
26
+ @use '../../styles/motion';
27
+ @use '../../styles/statelayer';
28
+ @use '../../styles/typography';
29
+
30
+ $disabled: ':is(:disabled, :has(input:disabled, > button:disabled))';
31
+ $enabled: ':not(:disabled, :has(input:disabled, > button:disabled))';
32
+ $focused: ':is(:focus-visible, :has(input:focus-visible))';
33
+
34
+ @include elevation.level(0);
35
+ @include elevation.level(1);
36
+ @include elevation.level(2);
37
+
38
+ @include statelayer.token('hover-state-layer-opacity');
39
+ @include statelayer.token('focus-state-layer-opacity');
40
+ @include statelayer.token('pressed-state-layer-opacity');
41
+ @include statelayer.token('disabled-state-layer-opacity');
42
+ @include statelayer.token('focus-indicator-thickness');
43
+ @include statelayer.token('ripple-opacity-factor');
44
+ @include statelayer.token('ripple-duration');
45
+ @include statelayer.property;
46
+ @include statelayer.keyframes;
47
+
48
+ @include typography.scale('label-large');
49
+
50
+ %micl-button-base {
51
+ --md-comp-button-motion-effects: #{motion.$md-sys-motion-expressive-fast-spatial};
52
+ --md-comp-button-motion-duration: #{motion.$md-sys-motion-expressive-fast-spatial-duration};
53
+ --micl-ripple: 1;
54
+
55
+ box-sizing: border-box;
56
+ position: relative;
57
+ display: inline-flex;
58
+ flex-shrink: 0;
59
+ align-items: center;
60
+ justify-content: center;
61
+ padding: 0;
62
+ border: none;
63
+ border-radius: calc(var(--micl-height) / 2);
64
+ background-image:
65
+ radial-gradient(
66
+ circle at var(--micl-x, center) var(--micl-y, center),
67
+ transparent 0%,
68
+ rgb(from var(--statelayer-color) r g b / calc(var(--statelayer-opacity) * var(--md-sys-state-ripple-opacity-factor))) 10%,
69
+ transparent 10%
70
+ ),
71
+ linear-gradient(rgb(from var(--statelayer-color) r g b / var(--statelayer-opacity)));
72
+ background-repeat: no-repeat;
73
+ background-position: var(--micl-x, center) var(--micl-y, center), 0 0;
74
+ background-size: 0%, 100%;
75
+ -webkit-tap-highlight-color: transparent;
76
+ cursor: pointer;
77
+ transition:
78
+ border-radius var(--md-comp-button-motion-duration) var(--md-comp-button-motion-effects),
79
+ box-shadow var(--md-comp-button-motion-duration) var(--md-comp-button-motion-effects),
80
+ background-size 0ms,
81
+ --statelayer-opacity var(--md-comp-button-motion-duration) linear;
82
+
83
+ &#{$disabled} {
84
+ cursor: default;
85
+ }
86
+ &#{$enabled} {
87
+ &:hover {
88
+ --statelayer-opacity: var(--md-sys-state-hover-state-layer-opacity, 8%);
89
+
90
+ .micl-button__icon {
91
+ font-variation-settings: 'FILL' 1;
92
+ }
93
+ }
94
+ &#{$focused} {
95
+ --statelayer-opacity: var(--md-sys-state-focus-state-layer-opacity, 10%);
96
+
97
+ outline: var(--md-sys-state-focus-indicator-thickness, 3px) solid var(--md-sys-color-secondary);
98
+ outline-offset: 2px;
99
+ }
100
+ &:active {
101
+ --statelayer-opacity: var(--md-sys-state-pressed-state-layer-opacity, 10%);
102
+ }
103
+ &.micl-rippling {
104
+ animation: micl-ripple calc(var(--md-sys-state-ripple-duration) * 1.333);
105
+ }
106
+ }
107
+ .micl-button__icon {
108
+ font-variation-settings: 'FILL' 0;
109
+ transition: font-variation-settings var(--md-comp-button-motion-duration) linear;
110
+ }
111
+ &.micl-button--toggle:not([aria-pressed="true"]) .micl-button__icon::before {
112
+ content: attr(data-miclicon);
113
+ }
114
+ &.micl-button--toggle[aria-pressed="true"] .micl-button__icon::before {
115
+ content: attr(data-micliconselected);
116
+ }
117
+ }
118
+
119
+ // Buttons smaller than the minimum touch target extend their interactive area with a
120
+ // transparent ::before overlay.
121
+ %micl-button-target {
122
+ &::before {
123
+ content: "";
124
+ position: absolute;
125
+ block-size: var(--md-sys-target-size, 48px);
126
+ inline-size: 100%;
127
+ min-inline-size: var(--md-sys-target-size, 48px);
128
+ inset: calc((var(--micl-height) - var(--md-sys-target-size, 48px)) / 2) 0 0 calc((min(100%, var(--md-sys-target-size, 48px)) - var(--md-sys-target-size, 48px)) / 2);
129
+ background-color: transparent;
130
+ }
131
+ }
132
+
133
+ %micl-button-xs {
134
+ @include typography.label-large;
135
+ @extend %micl-button-target;
136
+
137
+ --micl-width: 32px;
138
+ --micl-height: 32px;
139
+
140
+ min-inline-size: var(--micl-width);
141
+ block-size: var(--micl-height);
142
+ min-block-size: var(--micl-height);
143
+ column-gap: 4px;
144
+ padding-inline: 12px;
145
+
146
+ .micl-button__icon {
147
+ font-size: 20px;
148
+ inline-size: 20px;
149
+ }
150
+ }
151
+
152
+ %micl-button-elevated {
153
+ --statelayer-color: var(--md-sys-color-primary);
154
+
155
+ background-color: var(--md-comp-elevated-button-container-color, var(--md-sys-color-surface-container-low));
156
+ color: var(--md-comp-elevated-button-label-text-color, var(--md-sys-color-primary));
157
+ box-shadow: var(--md-comp-elevated-button-container-elevation, var(--md-sys-elevation-level1));
158
+
159
+ &#{$disabled} {
160
+ background-color: var(--md-comp-elevated-button-disabled-container-color, rgb(from var(--md-sys-color-on-surface) r g b / var(--md-comp-elevated-button-disabled-container-opacity, 10%)));
161
+ color: var(--md-comp-elevated-button-disabled-label-text-color, rgb(from var(--md-sys-color-on-surface-variant) r g b / var(--md-comp-elevated-button-disabled-label-text-opacity, 38%)));
162
+ box-shadow: var(--md-sys-elevation-level0);
163
+ }
164
+ &#{$enabled} {
165
+ &:hover:not(:active) {
166
+ box-shadow: var(--md-sys-elevation-level2);
167
+ }
168
+ &.micl-button--toggle[aria-pressed="true"] {
169
+ --statelayer-color: var(--md-sys-color-on-primary);
170
+
171
+ background-color: var(--md-comp-elevated-button-selected-container-color, var(--md-sys-color-primary));
172
+ color: var(--md-comp-elevated-button-selected-label-text-color, var(--md-sys-color-on-primary));
173
+
174
+ .micl-button__icon {
175
+ font-variation-settings: 'FILL' 1;
176
+ }
177
+ }
178
+ }
179
+ }
180
+
181
+ %micl-button-outlined {
182
+ --statelayer-color: var(--md-sys-color-on-surface-variant);
183
+
184
+ background-color: transparent;
185
+ color: var(--md-comp-outlined-button-label-text-color, var(--md-sys-color-on-surface-variant));
186
+ border: 1px solid var(--md-comp-outlined-button-outline-color, var(--md-sys-color-outline-variant));
187
+
188
+ &#{$disabled} {
189
+ background-color: transparent;
190
+ color: var(--md-comp-outlined-button-disabled-label-text-color, rgb(from var(--md-sys-color-on-surface-variant) r g b / var(--md-comp-outlined-button-disabled-label-text-opacity, 38%)));
191
+
192
+ &.micl-button--toggle[aria-pressed="true"] {
193
+ border: none;
194
+ background-color: var(--md-comp-outlined-button-selected-disabled-container-color, rgb(from var(--md-sys-color-on-surface) r g b / var(--md-comp-outlined-button-selected-disabled-container-opacity, 10%)));
195
+ }
196
+ }
197
+ &#{$enabled} {
198
+ &.micl-button--toggle[aria-pressed="true"] {
199
+ --statelayer-color: var(--md-sys-color-inverse-on-surface);
200
+
201
+ border: none;
202
+ background-color: var(--md-comp-outlined-button-selected-container-color, var(--md-sys-color-inverse-surface));
203
+ color: var(--md-comp-outlined-button-selected-label-text-color, var(--md-sys-color-inverse-on-surface));
204
+
205
+ .micl-button__icon {
206
+ font-variation-settings: 'FILL' 1;
207
+ }
208
+ }
209
+ }
210
+ }
@@ -19,311 +19,118 @@
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
- @use '../../styles/elevation';
24
- @use '../../styles/motion';
25
22
  @use '../../styles/shape';
26
- @use '../../styles/statelayer';
27
23
  @use '../../styles/typography';
24
+ @use './shared' as *;
28
25
 
29
- @include elevation.level(0);
30
- @include elevation.level(1);
26
+ $buttons: ':is([class*="micl-button-text-"], [class*="micl-button-elevated-"], [class*="micl-button-filled-"], [class*="micl-button-tonal-"], [class*="micl-button-outlined-"])';
31
27
 
32
28
  @include shape.corner('small');
33
29
  @include shape.corner('medium');
34
30
  @include shape.corner('large');
35
31
  @include shape.corner('extra-large');
36
32
 
37
- @include statelayer.token('hover-state-layer-opacity');
38
- @include statelayer.token('focus-state-layer-opacity');
39
- @include statelayer.token('pressed-state-layer-opacity');
40
- @include statelayer.token('disabled-state-layer-opacity');
41
- @include statelayer.token('focus-indicator-thickness');
42
- @include statelayer.token('ripple-opacity-factor');
43
- @include statelayer.token('ripple-duration');
44
- @include statelayer.property;
45
- @include statelayer.keyframes;
46
-
47
33
  @include typography.scale('headline-large');
48
34
  @include typography.scale('headline-small');
49
35
  @include typography.scale('title-medium');
50
- @include typography.scale('label-large');
51
-
52
- [class*="micl-button-text-"],
53
- [class*="micl-button-elevated-"],
54
- [class*="micl-button-filled-"],
55
- [class*="micl-button-tonal-"],
56
- [class*="micl-button-outlined-"] {
57
- --md-sys-button-motion-effects: #{motion.$md-sys-motion-expressive-fast-spatial};
58
- --md-sys-button-motion-duration: #{motion.$md-sys-motion-expressive-fast-spatial-duration};
59
- --md-sys-button-motion-duration-reverse: #{motion.$md-sys-motion-expressive-fast-spatial-duration};
60
- --micl-ripple: 1;
61
-
62
- position: relative;
63
- display: inline-flex;
64
- flex-shrink: 0;
65
- align-items: center;
66
- justify-content: center;
67
- padding: 0;
68
- border: none;
69
- border-radius: calc(var(--micl-height) / 2);
70
- background-image:
71
- radial-gradient(
72
- circle at var(--micl-x, center) var(--micl-y, center),
73
- transparent 0%,
74
- rgb(from var(--statelayer-color) r g b / calc(var(--statelayer-opacity) * var(--md-sys-state-ripple-opacity-factor))) 10%,
75
- transparent 10%
76
- ),
77
- linear-gradient(rgb(from var(--statelayer-color) r g b / var(--statelayer-opacity)));
78
- background-repeat: no-repeat;
79
- background-size: 0%, 100%;
80
- -webkit-tap-highlight-color: transparent;
81
- cursor: pointer;
82
- transition:
83
- border-radius var(--md-sys-button-motion-duration) var(--md-sys-button-motion-effects),
84
- background-size 0ms,
85
- --statelayer-opacity var(--md-sys-button-motion-duration) linear;
86
-
87
- &:disabled {
88
- box-shadow: var(--md-sys-elevation-level0);
89
- cursor: default;
90
- }
91
- &:not(:disabled) {
92
- &:hover {
93
- --statelayer-opacity: var(--md-sys-state-hover-state-layer-opacity, 8%);
94
36
 
95
- .micl-button__icon {
96
- font-variation-settings: 'FILL' 1;
97
- }
98
- }
99
- &:focus-visible {
100
- --statelayer-opacity: var(--md-sys-state-focus-state-layer-opacity, 10%);
37
+ #{$buttons} {
38
+ @extend %micl-button-base;
101
39
 
102
- outline: var(--md-sys-state-focus-indicator-thickness, 3px) solid var(--md-sys-color-secondary);
103
- outline-offset: 3px;
104
- }
105
- &:active {
106
- --statelayer-opacity: var(--md-sys-state-pressed-state-layer-opacity, 10%);
107
- }
108
- &.micl-rippling {
109
- animation: micl-ripple var(--md-sys-state-ripple-duration) motion.$md-sys-motion-easing-standard;
110
- }
111
- }
112
- .micl-button__icon {
113
- font-variation-settings: 'FILL' 0;
114
- transition: font-variation-settings var(--md-sys-button-motion-duration) linear;
115
- }
116
- &.micl-button--toggle:not([aria-pressed="true"]) .micl-button__icon::before {
117
- content: attr(data-miclicon);
118
- }
119
- &.micl-button--toggle[aria-pressed="true"] .micl-button__icon::before {
120
- content: attr(data-micliconselected);
121
- }
122
- }
123
-
124
- .micl-button-text-xs,
125
- .micl-button-elevated-xs,
126
- .micl-button-filled-xs,
127
- .micl-button-tonal-xs,
128
- .micl-button-outlined-xs {
129
- @include typography.label-large;
130
-
131
- --micl-width: 32px;
132
- --micl-height: 32px;
133
-
134
- position: relative;
135
40
  min-inline-size: var(--micl-width);
136
41
  block-size: var(--micl-height);
137
42
  min-block-size: var(--micl-height);
138
- column-gap: 4px;
139
- padding-inline: 12px;
140
-
141
- &::before {
142
- content: "";
143
- position: absolute;
144
- block-size: var(--md-sys-target-size, 48px);
145
- inline-size: 100%;
146
- min-inline-size: var(--md-sys-target-size, 48px);
147
- inset: calc((var(--micl-height) - var(--md-sys-target-size, 48px)) / 2) 0 0 calc((min(100%, var(--md-sys-target-size, 48px)) - var(--md-sys-target-size, 48px)) / 2);
148
- background-color: transparent;
149
- }
43
+
44
+ // The corner rounding of the size modifiers resolves through the two --_shape-*
45
+ // custom properties that each size declares below.
150
46
  &.micl-button--toggle[aria-pressed="true"] {
151
- border-radius: var(--md-sys-shape-corner-medium);
47
+ border-radius: var(--_shape-toggle);
152
48
  }
153
49
  &.micl-button--square {
154
- border-radius: var(--md-sys-shape-corner-medium);
50
+ border-radius: var(--_shape-toggle);
155
51
 
156
52
  &.micl-button--toggle[aria-pressed="true"] {
157
53
  border-radius: calc(var(--micl-height) / 2);
158
54
  }
159
55
  }
160
- &:not(:disabled):active {
56
+ &#{$enabled}:active {
161
57
  &,
162
58
  &.micl-button--square {
163
- border-radius: var(--md-sys-shape-corner-small);
59
+ border-radius: var(--_shape-pressed);
164
60
  }
165
61
  }
166
- .micl-button__icon {
167
- font-size: 20px;
168
- inline-size: 20px;
169
- }
170
62
  }
171
63
 
172
- .micl-button-text-s,
173
- .micl-button-elevated-s,
174
- .micl-button-filled-s,
175
- .micl-button-tonal-s,
176
- .micl-button-outlined-s {
64
+ :is(.micl-button-text-xs, .micl-button-elevated-xs, .micl-button-filled-xs, .micl-button-tonal-xs, .micl-button-outlined-xs) {
65
+ @extend %micl-button-xs;
66
+
67
+ --_shape-toggle: var(--md-sys-shape-corner-medium);
68
+ --_shape-pressed: var(--md-sys-shape-corner-small);
69
+ }
70
+
71
+ :is(.micl-button-text-s, .micl-button-elevated-s, .micl-button-filled-s, .micl-button-tonal-s, .micl-button-outlined-s) {
177
72
  @include typography.label-large;
73
+ @extend %micl-button-target;
178
74
 
179
75
  --micl-width: 40px;
180
76
  --micl-height: 40px;
77
+ --_shape-toggle: var(--md-sys-shape-corner-medium);
78
+ --_shape-pressed: var(--md-sys-shape-corner-small);
181
79
 
182
- min-inline-size: var(--micl-width);
183
- block-size: var(--micl-height);
184
- min-block-size: var(--micl-height);
185
80
  column-gap: 8px;
186
81
  padding-inline: 16px;
187
82
 
188
- &::before {
189
- content: "";
190
- position: absolute;
191
- block-size: var(--md-sys-target-size, 48px);
192
- inline-size: 100%;
193
- min-inline-size: var(--md-sys-target-size, 48px);
194
- inset: calc((var(--micl-height) - var(--md-sys-target-size, 48px)) / 2) 0 0 calc((min(100%, var(--md-sys-target-size, 48px)) - var(--md-sys-target-size, 48px)) / 2);
195
- background-color: transparent;
196
- }
197
- &.micl-button--toggle[aria-pressed="true"] {
198
- border-radius: var(--md-sys-shape-corner-medium);
199
- }
200
- &.micl-button--square {
201
- border-radius: var(--md-sys-shape-corner-medium);
202
-
203
- &.micl-button--toggle[aria-pressed="true"] {
204
- border-radius: calc(var(--micl-height) / 2);
205
- }
206
- }
207
- &:not(:disabled):active {
208
- &,
209
- &.micl-button--square {
210
- border-radius: var(--md-sys-shape-corner-small);
211
- }
212
- }
213
83
  .micl-button__icon {
214
84
  font-size: 20px;
215
85
  inline-size: 20px;
216
86
  }
217
87
  }
218
88
 
219
- .micl-button-text-m,
220
- .micl-button-elevated-m,
221
- .micl-button-filled-m,
222
- .micl-button-tonal-m,
223
- .micl-button-outlined-m {
89
+ :is(.micl-button-text-m, .micl-button-elevated-m, .micl-button-filled-m, .micl-button-tonal-m, .micl-button-outlined-m) {
224
90
  @include typography.title-medium;
225
91
 
226
92
  --micl-width: 56px;
227
93
  --micl-height: 56px;
94
+ --_shape-toggle: var(--md-sys-shape-corner-large);
95
+ --_shape-pressed: var(--md-sys-shape-corner-medium);
228
96
 
229
- min-inline-size: var(--micl-width);
230
- block-size: var(--micl-height);
231
- min-block-size: var(--micl-height);
232
97
  column-gap: 8px;
233
98
  padding-inline: 24px;
234
99
 
235
- &.micl-button--toggle[aria-pressed="true"] {
236
- border-radius: var(--md-sys-shape-corner-large);
237
- }
238
- &.micl-button--square {
239
- border-radius: var(--md-sys-shape-corner-large);
240
-
241
- &.micl-button--toggle[aria-pressed="true"] {
242
- border-radius: calc(var(--micl-height) / 2);
243
- }
244
- }
245
- &:not(:disabled):active {
246
- &,
247
- &.micl-button--square {
248
- border-radius: var(--md-sys-shape-corner-medium);
249
- }
250
- }
251
100
  .micl-button__icon {
252
101
  font-size: var(--md-sys-icon-size, 24px);
253
102
  inline-size: var(--md-sys-icon-size, 24px);
254
103
  }
255
104
  }
256
105
 
257
- .micl-button-text-l,
258
- .micl-button-elevated-l,
259
- .micl-button-filled-l,
260
- .micl-button-tonal-l,
261
- .micl-button-outlined-l {
106
+ :is(.micl-button-text-l, .micl-button-elevated-l, .micl-button-filled-l, .micl-button-tonal-l, .micl-button-outlined-l) {
262
107
  @include typography.headline-small;
263
108
 
264
109
  --micl-width: 96px;
265
110
  --micl-height: 96px;
111
+ --_shape-toggle: var(--md-sys-shape-corner-extra-large);
112
+ --_shape-pressed: var(--md-sys-shape-corner-large);
266
113
 
267
- min-inline-size: var(--micl-width);
268
- block-size: var(--micl-height);
269
- min-block-size: var(--micl-height);
270
114
  column-gap: 12px;
271
115
  padding-inline: 48px;
272
116
 
273
- &.micl-button--toggle[aria-pressed="true"] {
274
- border-radius: var(--md-sys-shape-corner-extra-large);
275
- }
276
- &.micl-button--square {
277
- border-radius: var(--md-sys-shape-corner-extra-large);
278
-
279
- &.micl-button--toggle[aria-pressed="true"] {
280
- border-radius: calc(var(--micl-height) / 2);
281
- }
282
- }
283
- &:not(:disabled):active {
284
- &,
285
- &.micl-button--square {
286
- border-radius: var(--md-sys-shape-corner-large);
287
- }
288
- }
289
117
  .micl-button__icon {
290
118
  font-size: 32px;
291
119
  inline-size: 32px;
292
120
  }
293
121
  }
294
122
 
295
- .micl-button-text-xl,
296
- .micl-button-elevated-xl,
297
- .micl-button-filled-xl,
298
- .micl-button-tonal-xl,
299
- .micl-button-outlined-xl {
123
+ :is(.micl-button-text-xl, .micl-button-elevated-xl, .micl-button-filled-xl, .micl-button-tonal-xl, .micl-button-outlined-xl) {
300
124
  @include typography.headline-large;
301
125
 
302
126
  --micl-width: 136px;
303
127
  --micl-height: 136px;
128
+ --_shape-toggle: var(--md-sys-shape-corner-extra-large);
129
+ --_shape-pressed: var(--md-sys-shape-corner-large);
304
130
 
305
- min-inline-size: var(--micl-width);
306
- block-size: var(--micl-height);
307
- min-block-size: var(--micl-height);
308
131
  column-gap: 16px;
309
132
  padding-inline: 64px;
310
133
 
311
- &.micl-button--toggle[aria-pressed="true"] {
312
- border-radius: var(--md-sys-shape-corner-extra-large);
313
- }
314
- &.micl-button--square {
315
- border-radius: var(--md-sys-shape-corner-extra-large);
316
-
317
- &.micl-button--toggle[aria-pressed="true"] {
318
- border-radius: calc(var(--micl-height) / 2);
319
- }
320
- }
321
- &:not(:disabled):active {
322
- &,
323
- &.micl-button--square {
324
- border-radius: var(--md-sys-shape-corner-large);
325
- }
326
- }
327
134
  .micl-button__icon {
328
135
  font-size: 40px;
329
136
  inline-size: 40px;
@@ -337,35 +144,14 @@
337
144
  color: var(--md-comp-text-button-label-text-color, var(--md-sys-color-primary));
338
145
  text-decoration: none;
339
146
 
340
- &:disabled {
147
+ &#{$disabled} {
341
148
  background-color: transparent;
342
- color: var(--md-comp-text-button-disabled-label-text-color, rgb(from var(--md-sys-color-on-surface) r g b / var(--md-comp-text-button-disabled-label-text-opacity, 38%)));
149
+ color: var(--md-comp-text-button-disabled-label-text-color, rgb(from var(--md-sys-color-on-surface-variant) r g b / var(--md-comp-text-button-disabled-label-text-opacity, 38%)));
343
150
  }
344
151
  }
345
152
 
346
153
  [class*="micl-button-elevated-"] {
347
- --statelayer-color: var(--md-sys-color-primary);
348
-
349
- background-color: var(--md-comp-elevated-button-container-color, var(--md-sys-color-surface-container-low));
350
- color: var(--md-comp-elevated-button-label-text-color, var(--md-sys-color-primary));
351
- box-shadow: var(--md-comp-elevated-button-container-elevation, var(--md-sys-elevation-level1));
352
-
353
- &:disabled {
354
- background-color: var(--md-comp-elevated-button-disabled-container-color, rgb(from var(--md-sys-color-on-surface) r g b / var(--md-comp-elevated-button-disabled-container-opacity, 10%)));
355
- color: var(--md-comp-elevated-button-disabled-label-text-color, rgb(from var(--md-sys-color-on-surface) r g b / var(--md-comp-elevated-button-disabled-label-text-opacity, 38%)));
356
- }
357
- &:not(:disabled) {
358
- &.micl-button--toggle[aria-pressed="true"] {
359
- --statelayer-color: var(--md-sys-color-on-primary);
360
-
361
- background-color: var(--md-comp-elevated-button-selected-container-color, var(--md-sys-color-primary));
362
- color: var(--md-comp-elevated-button-selected-label-text-color, var(--md-sys-color-on-primary));
363
-
364
- .micl-button__icon {
365
- font-variation-settings: 'FILL' 1;
366
- }
367
- }
368
- }
154
+ @extend %micl-button-elevated;
369
155
  }
370
156
 
371
157
  [class*="micl-button-filled-"] {
@@ -374,11 +160,14 @@
374
160
  background-color: var(--md-comp-filled-button-container-color, var(--md-sys-color-primary));
375
161
  color: var(--md-comp-filled-button-label-text-color, var(--md-sys-color-on-primary));
376
162
 
377
- &:disabled {
163
+ &#{$disabled} {
378
164
  background-color: var(--md-comp-filled-button-disabled-container-color, rgb(from var(--md-sys-color-on-surface) r g b / var(--md-comp-filled-button-disabled-container-opacity, 10%)));
379
- color: var(--md-comp-filled-button-disabled-label-text-color, rgb(from var(--md-sys-color-on-surface) r g b / var(--md-comp-filled-button-disabled-label-text-opacity, 38%)));
165
+ color: var(--md-comp-filled-button-disabled-label-text-color, rgb(from var(--md-sys-color-on-surface-variant) r g b / var(--md-comp-filled-button-disabled-label-text-opacity, 38%)));
380
166
  }
381
- &:not(:disabled) {
167
+ &#{$enabled} {
168
+ &:hover:not(:active) {
169
+ box-shadow: var(--md-sys-elevation-level1);
170
+ }
382
171
  &.micl-button--toggle[aria-pressed="true"] {
383
172
  .micl-button__icon {
384
173
  font-variation-settings: 'FILL' 1;
@@ -399,11 +188,14 @@
399
188
  background-color: var(--md-comp-filled-tonal-button-container-color, var(--md-sys-color-secondary-container));
400
189
  color: var(--md-comp-filled-tonal-button-label-text-color, var(--md-sys-color-on-secondary-container));
401
190
 
402
- &:disabled {
191
+ &#{$disabled} {
403
192
  background-color: var(--md-comp-filled-tonal-button-disabled-container-color, rgb(from var(--md-sys-color-on-surface) r g b / var(--md-comp-filled-tonal-button-disabled-container-opacity, 10%)));
404
- color: var(--md-comp-filled-tonal-button-disabled-label-text-color, rgb(from var(--md-sys-color-on-surface) r g b / var(--md-comp-filled-tonal-button-disabled-label-text-opacity, 38%)));
193
+ color: var(--md-comp-filled-tonal-button-disabled-label-text-color, rgb(from var(--md-sys-color-on-surface-variant) r g b / var(--md-comp-filled-tonal-button-disabled-label-text-opacity, 38%)));
405
194
  }
406
- &:not(:disabled) {
195
+ &#{$enabled} {
196
+ &:hover:not(:active) {
197
+ box-shadow: var(--md-sys-elevation-level1);
198
+ }
407
199
  &.micl-button--toggle[aria-pressed="true"] {
408
200
  --statelayer-color: var(--md-sys-color-on-secondary);
409
201
 
@@ -418,37 +210,11 @@
418
210
  }
419
211
 
420
212
  [class*="micl-button-outlined-"] {
421
- --statelayer-color: var(--md-sys-color-on-surface-variant);
422
-
423
- background-color: transparent;
424
- color: var(--md-comp-outlined-button-label-text-color, var(--md-sys-color-on-surface-variant));
425
-
426
- &:disabled {
427
- background-color: transparent;
428
- color: var(--md-comp-outlined-button-disabled-label-text-color, rgb(from var(--md-sys-color-on-surface) r g b / var(--md-comp-outlined-button-disabled-label-text-opacity, 38%)));
429
- }
430
- &:not(:disabled) {
431
- &.micl-button--toggle[aria-pressed="true"] {
432
- --statelayer-color: var(--md-sys-color-inverse-on-surface);
433
-
434
- border: none;
435
- background-color: var(--md-comp-outlined-button-selected-container-color, var(--md-sys-color-inverse-surface));
436
- color: var(--md-comp-outlined-button-selected-label-text-color, var(--md-sys-color-inverse-on-surface));
437
-
438
- .micl-button__icon {
439
- font-variation-settings: 'FILL' 1;
440
- }
441
- }
442
- }
443
- }
444
- .micl-button-outlined-xs,
445
- .micl-button-outlined-s,
446
- .micl-button-outlined-m {
447
- border: 1px solid var(--md-comp-outlined-button-outline-color, var(--md-sys-color-outline-variant));
213
+ @extend %micl-button-outlined;
448
214
  }
449
215
  .micl-button-outlined-l {
450
- border: 2px solid var(--md-comp-outlined-button-outline-color, var(--md-sys-color-outline-variant));
216
+ border-width: 2px;
451
217
  }
452
218
  .micl-button-outlined-xl {
453
- border: 3px solid var(--md-comp-outlined-button-outline-color, var(--md-sys-color-outline-variant));
219
+ border-width: 3px;
454
220
  }