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
@@ -1,5 +1,5 @@
1
1
  //
2
- // Copyright © 2025 Hermana AS
2
+ // Copyright © 2026 Hermana AS
3
3
  //
4
4
  // Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  // of this software and associated documentation files (the "Software"), to deal
@@ -19,207 +19,657 @@
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
 
25
- @include motion.duration('long2');
26
- @include motion.duration('extra-long4');
24
+ $track-color: var(--md-comp-linear-progress-track-color, var(--md-sys-color-secondary-container));
25
+ $active-color: var(--md-comp-linear-progress-active-indicator-color, var(--md-sys-color-primary));
26
+ $stop-dot: radial-gradient(circle closest-side,
27
+ var(--md-comp-linear-progress-stop-color, var(--md-sys-color-primary)) calc(100% - 0.75px),
28
+ transparent);
27
29
 
28
- // Registered so determinate updates from the JS handler interpolate smoothly.
29
- // Never keyframe-animated.
30
- @property --md-comp-progress-fraction {
31
- syntax: '<number>';
32
- initial-value: 0;
33
- inherits: true;
30
+ @property --micl-progress-tail {
31
+ syntax: '<percentage>';
32
+ inherits: false;
33
+ initial-value: 0%;
34
+ }
35
+ @property --micl-progress-stop-color {
36
+ syntax: '<color>';
37
+ inherits: false;
38
+ initial-value: transparent;
39
+ }
40
+ @property --micl-progress-size {
41
+ syntax: '<percentage>';
42
+ inherits: false;
43
+ initial-value: 0%;
34
44
  }
45
+ @property --micl-progress-space {
46
+ syntax: '<length>';
47
+ inherits: false;
48
+ initial-value: 4px;
49
+ }
50
+ @property --micl-progress-track-color {
51
+ syntax: '<color>';
52
+ inherits: false;
53
+ initial-value: transparent;
54
+ }
55
+ $carve-stops: "var(--micl-progress-track-color) calc(var(--micl-progress-tail) - var(--micl-progress-space)), transparent 0, transparent calc(var(--micl-progress-tail) + var(--micl-progress-size) + var(--micl-progress-space)), var(--micl-progress-track-color) 0";
35
56
 
36
- // Non-themed defaults. Declared on :root so they can be overridden on :root or
37
- // any parent element (consistent with the other MICL components). The colour
38
- // roles are resolved per the M3 progress-indicator spec at the point of use
39
- // (see $active/$track/$stop) because the theme palette is scoped to the
40
- // .light/.dark window class and is therefore NOT in scope at :root.
41
- :root {
42
- --md-comp-progress-thickness: 4px;
43
- --md-comp-progress-track-gap: 4px;
44
- --md-comp-progress-stop-size: 4px;
45
- --md-comp-progress-linear-width: 100%;
46
- --md-comp-progress-wave-wavelength: 40px;
47
- --md-comp-progress-wave-amplitude: 3px;
48
- --md-comp-progress-indeterminate-duration: var(--md-sys-motion-duration-extra-long4);
49
- --md-comp-progress-circular-size: 48px;
50
- --md-comp-progress-amplitude-scale: 1;
51
-
52
- // One wavelength of a sine ribbon, stroked at a constant width, used as a
53
- // static mask so the active indicator takes a wavy shape. Painted once —
54
- // no animation, no per-frame cost. The stroke is WHITE so it reveals
55
- // correctly whether the browser treats the SVG mask as alpha (white =
56
- // opaque) or luminance (white = 1).
57
- --md-comp-progress-wave-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 10' preserveAspectRatio='none'%3E%3Cpath d='M0 5 Q10 -1 20 5 T40 5' fill='none' stroke='white' stroke-width='4' stroke-linecap='round'/%3E%3C/svg%3E");
58
- }
59
-
60
- // M3 progress-indicator colour mapping. Resolved on the component element so
61
- // the system palette (scoped to the themed window ancestor) is in scope; a
62
- // consumer-supplied --md-comp-progress-*-color on any ancestor still wins.
63
- $active: var(--md-comp-progress-active-color, var(--md-sys-color-primary));
64
- $track: var(--md-comp-progress-track-color, var(--md-sys-color-secondary-container));
65
- $stop: var(--md-comp-progress-stop-color, var(--md-sys-color-primary));
66
-
67
- %progress-reset {
68
- -webkit-appearance: none;
69
- appearance: none;
70
- border: none;
71
- margin: 0;
72
- background-color: transparent;
73
- color: $active;
74
- vertical-align: middle;
57
+ @property --micl-progress-thickness {
58
+ syntax: '<length>';
59
+ inherits: false;
60
+ initial-value: 4px;
75
61
  }
62
+ $det-dot: radial-gradient(circle closest-side,
63
+ var(--micl-progress-stop-color) calc(100% - 0.75px), transparent);
64
+ $det-carve: "calc(var(--micl-progress-tail) + min(var(--micl-progress-tail), var(--micl-progress-space)))";
65
+ $det-bar-end: "calc(var(--micl-progress-tail) - var(--micl-progress-thickness) / 2)";
66
+ $det-bar-body: linear-gradient(to right,
67
+ var(--micl-progress-active-color) 0 #{$det-bar-end}, transparent 0);
68
+ $det-bar-body-rtl: linear-gradient(to left,
69
+ var(--micl-progress-active-color) 0 #{$det-bar-end}, transparent 0);
70
+ $det-bar-cap: radial-gradient(circle calc(var(--micl-progress-thickness) / 2) at #{$det-bar-end} 50%,
71
+ var(--micl-progress-active-color) calc(100% - 0.75px), transparent);
72
+ $det-bar-cap-rtl: radial-gradient(circle calc(var(--micl-progress-thickness) / 2) at calc(100% - #{$det-bar-end}) 50%,
73
+ var(--micl-progress-active-color) calc(100% - 0.75px), transparent);
76
74
 
77
- // Static wavy active indicator. No animation: the mask is rasterised once and
78
- // never sampled again, so a screen full of determinate indicators costs
79
- // nothing per frame.
80
- @mixin wave {
81
- background-color: $active;
82
- -webkit-mask-image: var(--md-comp-progress-wave-image);
83
- mask-image: var(--md-comp-progress-wave-image);
84
- -webkit-mask-repeat: repeat-x;
85
- mask-repeat: repeat-x;
86
- -webkit-mask-position: 0 center;
87
- mask-position: 0 center;
88
- -webkit-mask-size: var(--md-comp-progress-wave-wavelength)
89
- calc(var(--md-comp-progress-thickness) + 2 * var(--md-comp-progress-wave-amplitude) * var(--md-comp-progress-amplitude-scale, 1));
90
- mask-size: var(--md-comp-progress-wave-wavelength)
91
- calc(var(--md-comp-progress-thickness) + 2 * var(--md-comp-progress-wave-amplitude) * var(--md-comp-progress-amplitude-scale, 1));
75
+ @property --micl-progress-sweep {
76
+ syntax: '<angle>';
77
+ inherits: false;
78
+ initial-value: 0deg;
79
+ }
80
+ @property --micl-progress-gap {
81
+ syntax: '<angle>';
82
+ inherits: false;
83
+ initial-value: 0deg;
84
+ }
85
+ @property --micl-progress-radius {
86
+ syntax: '<length>';
87
+ inherits: false;
88
+ initial-value: 0px;
89
+ }
90
+ @property --micl-progress-active-color {
91
+ syntax: '<color>';
92
+ inherits: false;
93
+ initial-value: transparent;
92
94
  }
95
+ $circ-track: var(--md-comp-circular-progress-track-color, var(--md-sys-color-secondary-container));
96
+ $circ-active: var(--md-comp-circular-progress-active-indicator-color, var(--md-sys-color-primary));
97
+ $circ-cap-active: radial-gradient(circle closest-side,
98
+ var(--micl-progress-active-color) calc(100% - 0.75px), transparent);
99
+ $circ-cap-track: radial-gradient(circle closest-side,
100
+ var(--micl-progress-track-color) calc(100% - 0.75px), transparent);
101
+ $circ-gap: "min(var(--micl-progress-sweep), var(--micl-progress-gap))";
93
102
 
94
- //
95
- // Linear progress indicator
96
- //
97
- progress.micl-progress-linear {
98
- @extend %progress-reset;
103
+ progress.micl-linear-progress {
104
+ --_track-thickness: var(--md-comp-linear-progress-track-thickness, 4px);
105
+ --_active-thickness: var(--md-comp-linear-progress-active-thickness, 4px);
106
+ --_gap-color: var(--_card-background-color, var(--md-sys-color-surface-container-low));
107
+ --_padding: calc((var(--_track-thickness) - var(--_active-thickness)) / 2);
108
+ --_space: var(--md-comp-linear-progress-track-active-space, 4px);
99
109
 
100
- display: inline-block;
101
- inline-size: var(--md-comp-progress-linear-width);
102
- block-size: calc(var(--md-comp-progress-thickness) + 2 * var(--md-comp-progress-wave-amplitude));
103
-
104
- // Track (remaining portion) + end stop indicator. Starts one track-gap
105
- // after the active indicator, clipped to --thickness tall and centred.
106
- @mixin track {
107
- background-color: transparent;
108
- background-image:
109
- radial-gradient(circle, #{$stop} 0 50%, transparent 50%),
110
- linear-gradient(90deg,
111
- transparent 0 calc(var(--md-comp-progress-fraction, 0) * 100% + var(--md-comp-progress-track-gap)),
112
- #{$track} calc(var(--md-comp-progress-fraction, 0) * 100% + var(--md-comp-progress-track-gap)) 100%);
110
+ appearance: none;
111
+ box-sizing: border-box;
112
+ block-size: max(var(--_track-thickness), var(--_active-thickness));
113
+ inline-size: 100%;
114
+ padding-block: max(var(--_padding), 0px);
115
+ border: none;
116
+ border-radius: calc(max(var(--_track-thickness), var(--_active-thickness)) / 2);
117
+ // the track is a vertically centered BAND so the active bar may be the
118
+ // thicker of the two; when the track is thicker (or equal) the band fills
119
+ // the box and renders exactly like a plain background fill
120
+ background-image: linear-gradient(#{$track-color}, #{$track-color});
121
+ background-position: 0 center;
122
+ background-size: 100% var(--_track-thickness);
123
+ background-repeat: no-repeat;
124
+ overflow: hidden;
125
+
126
+ &:not(:indeterminate) {
127
+ --_size: var(--md-comp-linear-progress-stop-size, 4px);
128
+ background-image: $stop-dot, linear-gradient(#{$track-color}, #{$track-color});
129
+ background-position: calc(100% - var(--md-comp-linear-progress-stop-trailing-space, 0px)) center, 0 center;
130
+ background-size: var(--_size) var(--_size), 100% var(--_track-thickness);
113
131
  background-repeat: no-repeat;
114
- background-position: right center, left center;
115
- background-size:
116
- var(--md-comp-progress-stop-size) var(--md-comp-progress-stop-size),
117
- 100% var(--md-comp-progress-thickness);
118
- border-radius: calc(var(--md-comp-progress-thickness) / 2);
132
+
133
+ &:dir(rtl) {
134
+ background-position-x: var(--md-comp-linear-progress-stop-trailing-space, 0px), 0;
135
+ }
136
+
137
+ &::-webkit-progress-value {
138
+ box-shadow: var(--_space) 0 0 0 var(--_gap-color), calc(-1 * var(--_space)) 0 0 0 var(--_gap-color);
139
+ }
140
+ &::-moz-progress-bar {
141
+ box-shadow: var(--_space) 0 0 0 var(--_gap-color), calc(-1 * var(--_space)) 0 0 0 var(--_gap-color);
142
+ }
143
+
144
+ @supports (inline-size: attr(value type(<number>))) {
145
+ --_fraction: min(calc(attr(value type(<number>), 0) / max(attr(max type(<number>), 1), 0.001)), 1);
146
+ --micl-progress-tail: calc(var(--_fraction) * 100%);
147
+ --micl-progress-space: var(--md-comp-linear-progress-track-active-space, 4px);
148
+ --micl-progress-thickness: var(--_active-thickness);
149
+ --micl-progress-track-color: #{$track-color};
150
+ --micl-progress-active-color: #{$active-color};
151
+ --micl-progress-stop-color: var(--md-comp-linear-progress-stop-color, var(--md-sys-color-primary));
152
+ transition: --micl-progress-tail motion.$md-sys-motion-duration-long2 linear;
153
+ background-color: transparent;
154
+ background-image: $det-dot, $det-bar-cap, $det-bar-body,
155
+ linear-gradient(to right, transparent #{$det-carve}, var(--micl-progress-track-color) #{$det-carve});
156
+ background-position: calc(100% - var(--md-comp-linear-progress-stop-trailing-space, 0px)) center,
157
+ left center, left center, 0 center;
158
+ background-size: var(--_size) var(--_size),
159
+ 100% var(--micl-progress-thickness), 100% var(--micl-progress-thickness), 100% var(--_track-thickness);
160
+
161
+ &:dir(rtl) {
162
+ background-image: $det-dot, $det-bar-cap-rtl, $det-bar-body-rtl,
163
+ linear-gradient(to left, transparent #{$det-carve}, var(--micl-progress-track-color) #{$det-carve});
164
+ background-position: var(--md-comp-linear-progress-stop-trailing-space, 0px) center,
165
+ left center, left center, 0 center;
166
+ }
167
+ &::-webkit-progress-value {
168
+ box-shadow: none;
169
+ background: none;
170
+ }
171
+ &::-moz-progress-bar {
172
+ box-shadow: none;
173
+ background: none;
174
+ }
175
+ }
176
+ }
177
+ &::-webkit-progress-bar {
178
+ background: none;
179
+ }
180
+ &::-webkit-progress-value {
181
+ block-size: var(--_active-thickness) !important;
182
+ border-radius: calc(var(--_active-thickness) / 2);
183
+ background-color: $active-color;
184
+ }
185
+ &::-moz-progress-bar {
186
+ block-size: var(--_active-thickness) !important;
187
+ border-radius: calc(var(--_active-thickness) / 2);
188
+ background-color: $active-color;
189
+ }
190
+ &:indeterminate {
191
+ --micl-progress-space: var(--md-comp-linear-progress-track-active-space, 4px);
192
+ --micl-progress-track-color: #{$track-color};
193
+ background: linear-gradient(to right, #{$carve-stops}) 0 center / 100% var(--_track-thickness) no-repeat;
194
+ animation: indettrack 1750ms motion.$md-sys-motion-easing-emphasized-accelerate infinite;
195
+
196
+ &:dir(rtl) {
197
+ background-image: linear-gradient(to left, #{$carve-stops});
198
+ }
199
+ }
200
+ @supports selector(::-moz-progress-bar) {
201
+ &:indeterminate:dir(rtl) {
202
+ background-image: linear-gradient(to right, #{$carve-stops});
203
+ animation-name: indettrackrtl;
204
+ }
205
+ }
206
+ &:indeterminate::-webkit-progress-value {
207
+ animation: indet 1750ms motion.$md-sys-motion-easing-emphasized-accelerate infinite;
208
+ }
209
+ &:indeterminate::-moz-progress-bar {
210
+ animation: indet 1750ms motion.$md-sys-motion-easing-emphasized-accelerate infinite;
211
+ }
212
+ &:indeterminate:dir(rtl)::-moz-progress-bar {
213
+ animation-name: indetrtl;
214
+ }
215
+ }
216
+ @keyframes indet {
217
+ 0% {
218
+ margin-inline-start: 0%;
219
+ inline-size: 0%;
220
+ }
221
+ 14.3% { // the tail waits out the spec's 250ms delay before chasing the head
222
+ margin-inline-start: 0%;
223
+ }
224
+ 100% {
225
+ margin-inline-start: 100%;
226
+ inline-size: 80%;
227
+ }
228
+ }
229
+ @keyframes indetrtl {
230
+ 0% {
231
+ margin-inline-end: 100%;
232
+ inline-size: 0%;
233
+ }
234
+ 14.3% {
235
+ margin-inline-end: 100%;
236
+ }
237
+ 100% {
238
+ margin-inline-end: -80%;
239
+ inline-size: 80%;
240
+ }
241
+ }
242
+ @keyframes indettrack {
243
+ 0% {
244
+ --micl-progress-tail: 0%;
245
+ --micl-progress-size: 0%;
246
+ }
247
+ 14.3% {
248
+ --micl-progress-tail: 0%;
249
+ }
250
+ 100% {
251
+ --micl-progress-tail: 100%;
252
+ --micl-progress-size: 80%;
253
+ }
254
+ }
255
+ @keyframes indettrackrtl {
256
+ 0% {
257
+ --micl-progress-tail: 100%;
258
+ --micl-progress-size: 0%;
259
+ }
260
+ 14.3% {
261
+ --micl-progress-tail: 100%;
262
+ }
263
+ 100% {
264
+ --micl-progress-tail: -80%;
265
+ --micl-progress-size: 80%;
266
+ }
267
+ }
268
+
269
+ progress.micl-circular-progress {
270
+ --_size: var(--md-comp-circular-progress-size, 40px);
271
+ --_thickness: var(--md-comp-circular-progress-active-thickness, 4px);
272
+ --_space: var(--md-comp-circular-progress-track-active-space, 4px);
273
+ --micl-progress-radius: calc((var(--_size) - var(--_thickness)) / 2);
274
+ --micl-progress-gap: atan2(calc(var(--_space) + var(--_thickness)), var(--micl-progress-radius));
275
+ --micl-progress-active-color: #{$circ-active};
276
+ --micl-progress-track-color: #{$circ-track};
277
+
278
+ appearance: none;
279
+ box-sizing: border-box;
280
+ display: inline-block;
281
+ vertical-align: middle;
282
+ inline-size: var(--_size);
283
+ block-size: var(--_size);
284
+ border: none;
285
+ background-color: transparent;
286
+ background-image: $circ-cap-active, $circ-cap-active,
287
+ conic-gradient(
288
+ var(--micl-progress-active-color) 0 var(--micl-progress-sweep),
289
+ transparent 0 calc(var(--micl-progress-sweep) + #{$circ-gap}),
290
+ var(--micl-progress-track-color) 0 calc(360deg - #{$circ-gap}),
291
+ transparent 0),
292
+ $circ-cap-track, $circ-cap-track;
293
+ background-position: 50% calc(50% - var(--micl-progress-radius)),
294
+ calc(50% + var(--micl-progress-radius) * sin(var(--micl-progress-sweep)))
295
+ calc(50% - var(--micl-progress-radius) * cos(var(--micl-progress-sweep))),
296
+ 0 0,
297
+ calc(50% + var(--micl-progress-radius) * sin(calc(var(--micl-progress-sweep) + #{$circ-gap})))
298
+ calc(50% - var(--micl-progress-radius) * cos(calc(var(--micl-progress-sweep) + #{$circ-gap}))),
299
+ calc(50% - var(--micl-progress-radius) * sin(#{$circ-gap}))
300
+ calc(50% - var(--micl-progress-radius) * cos(#{$circ-gap}));
301
+ background-size: var(--_thickness) var(--_thickness), var(--_thickness) var(--_thickness),
302
+ 100% 100%, var(--_thickness) var(--_thickness), var(--_thickness) var(--_thickness);
303
+ background-repeat: no-repeat;
304
+ mask-image: radial-gradient(circle closest-side,
305
+ transparent calc(100% - var(--_thickness) - 0.5px),
306
+ #fff calc(100% - var(--_thickness) + 0.5px) calc(100% - 0.5px),
307
+ transparent);
308
+
309
+ @supports (clip-path: shape(from 0px 0px, arc to 1px 1px of 1px)) {
310
+ mask-image: none;
311
+ clip-path: shape(evenodd from 50% 0%,
312
+ arc to 50% 100% of calc(var(--_size) / 2),
313
+ arc to 50% 0% of calc(var(--_size) / 2),
314
+ move to 50% var(--_thickness),
315
+ arc to 50% calc(100% - var(--_thickness)) of calc(var(--_size) / 2 - var(--_thickness)),
316
+ arc to 50% var(--_thickness) of calc(var(--_size) / 2 - var(--_thickness)),
317
+ close);
119
318
  }
120
319
 
121
- &::-webkit-progress-bar { @include track; }
122
- &::-webkit-progress-value { @include wave; }
123
- &::-moz-progress-bar { @include wave; }
320
+ &::-webkit-progress-bar {
321
+ background: none;
322
+ }
323
+ &::-webkit-progress-value {
324
+ background: none;
325
+ }
326
+ &::-moz-progress-bar {
327
+ background: none;
328
+ }
124
329
 
125
- // Firefox renders the track on the element itself.
126
- @-moz-document url-prefix() {
127
- @include track;
330
+ @supports (inline-size: attr(value type(<number>))) {
331
+ &:not(:indeterminate) {
332
+ --micl-progress-sweep: calc(min(calc(attr(value type(<number>), 0) / max(attr(max type(<number>), 1), 0.001)), 1) * 360deg);
333
+ transition: --micl-progress-sweep motion.$md-sys-motion-duration-long2 motion.$md-sys-motion-easing-standard;
334
+ }
128
335
  }
129
336
 
130
- // Indeterminate: a comet sweeping a transparent track. Only this transient
131
- // state animates; the move is a single small repainted strip.
132
337
  &:indeterminate {
133
- background-image:
134
- linear-gradient(90deg, transparent, #{$active}, transparent),
135
- linear-gradient(#{$track}, #{$track});
338
+ animation: circglobal 6000ms linear infinite,
339
+ circstep 6000ms linear infinite,
340
+ circsweep 6000ms infinite;
341
+ }
342
+ }
343
+ @keyframes circglobal {
344
+ to {
345
+ rotate: 1080deg;
346
+ }
347
+ }
348
+ @keyframes circstep {
349
+ 0% {
350
+ transform: rotate(0deg);
351
+ }
352
+ 5% { // 300ms
353
+ transform: rotate(90deg);
354
+ }
355
+ 25% { // hold till 1500ms
356
+ transform: rotate(90deg);
357
+ }
358
+ 30% { // 1800ms
359
+ transform: rotate(180deg);
360
+ }
361
+ 50% { // hold till 3000ms
362
+ transform: rotate(180deg);
363
+ }
364
+ 55% { // 3300ms
365
+ transform: rotate(270deg);
366
+ }
367
+ 75% { // hold till 4500ms
368
+ transform: rotate(270deg);
369
+ }
370
+ 80% { // 4800ms
371
+ transform: rotate(360deg);
372
+ }
373
+ 100% { // hold till 6000ms - without this frame CSS fills in the underlying
374
+ // transform (0deg) and the last fifth of the cycle spins backwards
375
+ transform: rotate(360deg);
376
+ }
377
+ }
378
+ @keyframes circsweep {
379
+ 0% { // the arc grows linearly...
380
+ --micl-progress-sweep: 36deg;
381
+ animation-timing-function: linear;
382
+ }
383
+ 50% { // ...and shrinks with standard easing
384
+ --micl-progress-sweep: 313.2deg;
385
+ animation-timing-function: motion.$md-sys-motion-easing-standard;
386
+ }
387
+ 100% {
388
+ --micl-progress-sweep: 36deg;
389
+ }
390
+ }
391
+
392
+ @property --micl-progress-amplitude {
393
+ syntax: '<number>';
394
+ inherits: true;
395
+ initial-value: 0;
396
+ }
397
+ @property --micl-progress-fraction {
398
+ syntax: '<number>';
399
+ inherits: true;
400
+ initial-value: 0;
401
+ }
402
+ @property --micl-progress-cap {
403
+ syntax: '<length>';
404
+ inherits: false;
405
+ initial-value: 0px;
406
+ }
407
+ @property --micl-progress-crawl {
408
+ syntax: '<angle>';
409
+ inherits: false;
410
+ initial-value: 0deg;
411
+ }
412
+
413
+ .micl-linear-progress:not(progress) {
414
+ --_wavelength: var(--md-comp-linear-progress-active-wave-wavelength, 40px);
415
+ --_wave-gap: var(--md-comp-linear-progress-track-active-space, 4px);
416
+ --_max-amplitude: var(--md-comp-linear-progress-active-wave-amplitude, 3px);
417
+ --_track-thickness: var(--md-comp-linear-progress-track-thickness, 4px);
418
+ --_active-thickness: var(--md-comp-linear-progress-active-thickness, 4px);
419
+ --_fraction: min(calc(attr(aria-valuenow type(<number>), 0) / max(attr(aria-valuemax type(<number>), 1), 0.001)), 1);
420
+ --micl-progress-fraction: var(--_fraction);
421
+ --micl-progress-amplitude: clamp(0, min(calc(var(--micl-progress-fraction) / 0.1), calc((1 - var(--micl-progress-fraction)) / 0.05)), 1);
422
+ transition: --micl-progress-fraction motion.$md-sys-motion-duration-long2 linear;
423
+
424
+ --_wave-image: var(--md-comp-linear-progress-wave-image, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -30 6.283 60' preserveAspectRatio='none'%3E%3Cpath vector-effect='non-scaling-stroke' stroke-width='4' stroke-linecap='round' fill='none' stroke='black' d='M0,0 C.512,.512 1.002,1 1.571,1 S2.629,.512 3.142,0 S4.144,-1 4.712,-1 S5.771,-.512 6.283,0'/%3E%3C/svg%3E"));
425
+ --_amplitude: calc(var(--micl-progress-amplitude) * var(--_max-amplitude));
426
+ --_wave-mask-size: var(--_wavelength) max(calc(var(--_active-thickness) + 1px), calc(var(--_amplitude) * 60));
427
+
428
+ position: relative;
429
+ inline-size: 100%;
430
+ block-size: max(var(--_track-thickness), calc(2 * var(--_max-amplitude) + var(--_active-thickness)));
431
+ overflow: clip;
432
+
433
+ $wave-carve: "calc(var(--micl-progress-fraction) * 100% + min(var(--micl-progress-fraction) * 100%, var(--_wave-gap)))";
434
+
435
+ &::before {
436
+ --_stop-size: var(--md-comp-linear-progress-stop-size, 4px);
437
+
438
+ content: "";
439
+ position: absolute;
440
+ inset: 0;
441
+ inline-size: 100%;
442
+ block-size: var(--_track-thickness);
443
+ inset-block-start: calc(50% - (var(--_track-thickness) / 2));
444
+ border-radius: calc(var(--_track-thickness) / 2);
445
+ background-image: $stop-dot,
446
+ linear-gradient(to right, transparent #{$wave-carve}, $track-color 0);
447
+ background-position: calc(100% - var(--md-comp-linear-progress-stop-trailing-space, 0px)) center, 0 0;
448
+ background-size: var(--_stop-size) var(--_stop-size), 100% 100%;
136
449
  background-repeat: no-repeat;
137
- background-position: -40% center, left center;
138
- background-size: 40% var(--md-comp-progress-thickness), 100% var(--md-comp-progress-thickness);
139
- border-radius: calc(var(--md-comp-progress-thickness) / 2);
140
- animation: micl-progress-linear-indeterminate var(--md-comp-progress-indeterminate-duration) var(--md-sys-motion-easing-standard, ease-in-out) infinite;
450
+ }
451
+ .micl-linear-progress__wave {
452
+ inline-size: calc(var(--micl-progress-fraction) * 100%);
453
+ block-size: 100%;
454
+ background-color: $active-color;
455
+ border-radius: calc(var(--_max-amplitude) + var(--_active-thickness) / 2);
456
+ mask-image: var(--_wave-image);
457
+ mask-repeat: repeat-x;
458
+ mask-size: var(--_wave-mask-size);
459
+ mask-position: left center;
460
+
461
+ @container style(--micl-progress-amplitude: 0) {
462
+ position: relative;
463
+ inset-block-start: calc(50% - var(--_active-thickness) / 2);
464
+ block-size: var(--_active-thickness);
465
+ border-radius: calc(var(--_active-thickness) / 2);
466
+ mask-image: none;
467
+ }
468
+ }
469
+ &:dir(rtl) {
470
+ &::before {
471
+ background-image: $stop-dot,
472
+ linear-gradient(to left, transparent #{$wave-carve}, $track-color 0);
473
+ background-position: var(--md-comp-linear-progress-stop-trailing-space, 0px) center, 0 0;
474
+ }
475
+ .micl-linear-progress__wave {
476
+ mask-position: right center;
477
+ }
478
+ }
479
+ &.micl-linear-progress--indeterminate {
480
+ --_wavelength: var(--md-comp-linear-progress-indeterminate-active-wave-wavelength, 20px);
481
+ --_fraction: 1;
482
+ --micl-progress-amplitude: 1;
483
+
484
+ $comet-head: "min(var(--micl-progress-tail) + var(--micl-progress-size), 100%)";
141
485
 
142
- &::-webkit-progress-bar,
143
- &::-webkit-progress-value { background: transparent; }
144
- &::-moz-progress-bar { background: transparent; }
486
+ &::before {
487
+ --micl-progress-space: var(--md-comp-linear-progress-track-active-space, 4px);
488
+ --micl-progress-track-color: #{$track-color};
489
+
490
+ background: linear-gradient(to right, #{$carve-stops});
491
+ animation: indettrack 1750ms motion.$md-sys-motion-easing-emphasized-accelerate infinite;
492
+ }
493
+ .micl-linear-progress__wave {
494
+ --micl-progress-cap: calc(var(--_max-amplitude) + var(--_active-thickness) / 2);
495
+
496
+ background: none;
497
+ mask-image: none;
498
+ clip-path: inset(0 calc(100% - #{$comet-head}) 0 var(--micl-progress-tail) round var(--micl-progress-cap));
499
+ animation: indettrack 1750ms motion.$md-sys-motion-easing-emphasized-accelerate infinite;
500
+
501
+ &::before {
502
+ content: "";
503
+ position: absolute;
504
+ inset-block: 0;
505
+ inset-inline-start: 0;
506
+ inline-size: calc(100% + var(--_wavelength));
507
+ background-color: $active-color;
508
+ mask-image: var(--_wave-image);
509
+ mask-repeat: repeat-x;
510
+ mask-size: var(--_wave-mask-size);
511
+ mask-position: left center;
512
+ animation: crawl-wave 1000ms linear infinite;
513
+
514
+ @media (prefers-reduced-motion: reduce) {
515
+ animation-play-state: paused;
516
+ }
517
+ }
518
+ }
519
+ &:dir(rtl) {
520
+ &::before {
521
+ background-image: linear-gradient(to left, #{$carve-stops});
522
+ }
523
+ .micl-linear-progress__wave {
524
+ clip-path: inset(0 var(--micl-progress-tail) 0 calc(100% - #{$comet-head}) round var(--micl-progress-cap));
525
+
526
+ &::before {
527
+ mask-position: right center;
528
+ animation-name: crawl-wave-rtl;
529
+ }
530
+ }
531
+ }
145
532
  }
146
533
  }
147
534
 
148
- @keyframes micl-progress-linear-indeterminate {
149
- 0% { background-position: -40% center, left center; }
150
- 100% { background-position: 140% center, left center; }
535
+ @keyframes crawl-wave {
536
+ to { translate: calc(-1 * var(--_wavelength)) 0; }
537
+ }
538
+ @keyframes crawl-wave-rtl {
539
+ to { translate: var(--_wavelength) 0; }
151
540
  }
152
541
 
153
- //
154
- // Circular progress indicator
155
- //
156
- // Determinate: a static conic-gradient ring punched by a radial mask (white =
157
- // kept under both alpha and luminance masking). It is painted once and never
158
- // animated, so it costs nothing per frame.
159
- //
160
- progress.micl-progress-circular {
161
- @extend %progress-reset;
542
+ .micl-circular-progress:not(progress) {
543
+ $wave-ring: var(--md-comp-circular-progress-wave-image, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath vector-effect='non-scaling-stroke' stroke-width='4' fill='none' stroke='black' d='M24,6C25.18,5.16 26.57,4.53 27.82,4.78C29.08,5.03 30.12,6.15 30.89,7.37C31.66,8.59 32.22,9.77 33.11,10.36C34,10.96 35.3,11.03 36.73,11.27C38.15,11.51 39.58,12.04 40.3,13.11C41.01,14.18 40.95,15.7 40.63,17.11C40.31,18.52 39.88,19.75 40.08,20.8C40.29,21.85 41.16,22.82 42,24C42.84,25.18 43.47,26.57 43.22,27.82C42.97,29.08 41.85,30.12 40.63,30.89C39.41,31.66 38.23,32.22 37.64,33.11C37.04,34 36.97,35.3 36.73,36.73C36.49,38.15 35.96,39.58 34.89,40.3C33.82,41.01 32.3,40.95 30.89,40.63C29.48,40.31 28.25,39.88 27.2,40.08C26.15,40.29 25.18,41.16 24,42C22.82,42.84 21.43,43.47 20.18,43.22C18.92,42.97 17.88,41.85 17.11,40.63C16.34,39.41 15.78,38.23 14.89,37.64C14,37.04 12.7,36.97 11.27,36.73C9.85,36.49 8.42,35.96 7.7,34.89C6.99,33.82 7.05,32.3 7.37,30.89C7.69,29.48 8.12,28.25 7.92,27.2C7.71,26.15 6.84,25.18 6,24C5.16,22.82 4.53,21.43 4.78,20.18C5.03,18.92 6.15,17.88 7.37,17.11C8.59,16.34 9.77,15.78 10.36,14.89C10.96,14 11.03,12.7 11.27,11.27C11.51,9.85 12.04,8.42 13.11,7.7C14.18,6.99 15.7,7.05 17.11,7.37C18.52,7.69 19.75,8.12 20.8,7.92C21.85,7.71 22.82,6.84 24,6Z'/%3E%3C/svg%3E"));
544
+ // the flat-ring mask for the track and the zero-amplitude arc (0.5px ramps
545
+ // for full-pixel gradient antialiasing); 75% of closest-side = the 0.375 *
546
+ // box ring radius
547
+ $flat-ring: radial-gradient(circle closest-side,
548
+ transparent calc(75% - var(--micl-progress-thickness) / 2 - 0.5px),
549
+ #fff calc(75% - var(--micl-progress-thickness) / 2 + 0.5px) calc(75% + var(--micl-progress-thickness) / 2 - 0.5px),
550
+ transparent calc(75% + var(--micl-progress-thickness) / 2 + 0.5px));
551
+ $wave-cap-r: "(var(--micl-progress-radius) + 1.6px * var(--micl-progress-amplitude) * sin(8 * (var(--micl-progress-sweep) + var(--micl-progress-crawl))))";
162
552
 
163
- --md-comp-progress-circular-gap-deg: 12deg;
553
+ --_size: var(--md-comp-circular-progress-size, 40px);
554
+ --_thickness: var(--md-comp-circular-progress-active-thickness, 4px);
555
+ --_space: var(--md-comp-circular-progress-track-active-space, 4px);
556
+ --_box: calc(var(--_size) * 1.2);
557
+ --_fraction: min(calc(attr(aria-valuenow type(<number>), 0) / max(attr(aria-valuemax type(<number>), 1), 0.001)), 1);
558
+ --micl-progress-fraction: var(--_fraction);
559
+ --micl-progress-amplitude: clamp(0, min(calc((var(--micl-progress-fraction) - 0.1) * 1000), calc((0.95 - var(--micl-progress-fraction)) * 1000)), 1);
560
+ transition: --micl-progress-fraction motion.$md-sys-motion-duration-long2 motion.$md-sys-motion-easing-standard;
164
561
 
562
+ position: relative;
165
563
  display: inline-block;
166
- box-sizing: border-box;
167
- inline-size: var(--md-comp-progress-circular-size);
168
- block-size: var(--md-comp-progress-circular-size);
169
- border-radius: 50%;
170
- background-image: conic-gradient(
171
- #{$active} 0
172
- max(0deg, calc(var(--md-comp-progress-fraction, 0) * 360deg - var(--md-comp-progress-circular-gap-deg))),
173
- transparent
174
- max(0deg, calc(var(--md-comp-progress-fraction, 0) * 360deg - var(--md-comp-progress-circular-gap-deg)))
175
- calc(var(--md-comp-progress-fraction, 0) * 360deg),
176
- #{$track} calc(var(--md-comp-progress-fraction, 0) * 360deg) 360deg);
177
- -webkit-mask: radial-gradient(farthest-side,
178
- transparent calc(100% - var(--md-comp-progress-thickness)),
179
- #fff calc(100% - var(--md-comp-progress-thickness)));
180
- mask: radial-gradient(farthest-side,
181
- transparent calc(100% - var(--md-comp-progress-thickness)),
182
- #fff calc(100% - var(--md-comp-progress-thickness)));
183
-
184
- &::-webkit-progress-bar,
185
- &::-webkit-progress-value { background: transparent; }
186
- &::-moz-progress-bar { background: transparent; }
187
-
188
- &.micl-progress-circular--s { --md-comp-progress-circular-size: 28px; }
189
- &.micl-progress-circular--m { --md-comp-progress-circular-size: 48px; }
190
- &.micl-progress-circular--l { --md-comp-progress-circular-size: 64px; }
191
-
192
- // Indeterminate: the canonical lightweight CSS spinner — a plain bordered
193
- // ring (no gradient, no mask) rotated by transform. Chrome promotes this to
194
- // a compositor layer, rasterises it once, and spins the texture on the GPU,
195
- // so it is essentially free per frame regardless of how many are visible.
196
- &:indeterminate {
197
- background-image: none;
198
- -webkit-mask: none;
199
- mask: none;
200
- border: var(--md-comp-progress-thickness) solid #{$track};
201
- border-block-start-color: $active;
202
- animation: micl-progress-circular-spin var(--md-comp-progress-indeterminate-duration) linear infinite;
564
+ vertical-align: middle;
565
+ inline-size: var(--_box);
566
+ block-size: var(--_box);
567
+
568
+ &::before,
569
+ &::after {
570
+ --micl-progress-sweep: calc(var(--micl-progress-fraction) * 360deg);
571
+ --micl-progress-radius: calc(var(--_box) * 0.375);
572
+ --micl-progress-gap: atan2(calc(var(--_space) + var(--_thickness)), var(--micl-progress-radius));
573
+ --micl-progress-thickness: var(--_thickness);
574
+
575
+ content: "";
576
+ position: absolute;
577
+ inset: 0;
578
+ background-repeat: no-repeat;
579
+ mask-image: $flat-ring;
203
580
  }
204
- }
581
+ &::before {
582
+ --micl-progress-track-color: #{$circ-track};
205
583
 
206
- @keyframes micl-progress-circular-spin {
207
- to { transform: rotate(360deg); }
208
- }
584
+ background-image: $circ-cap-track, $circ-cap-track,
585
+ conic-gradient(
586
+ transparent 0 calc(var(--micl-progress-sweep) + #{$circ-gap}),
587
+ var(--micl-progress-track-color) 0 calc(360deg - #{$circ-gap}),
588
+ transparent 0);
589
+ background-position:
590
+ calc(50% + var(--micl-progress-radius) * sin(calc(var(--micl-progress-sweep) + #{$circ-gap})))
591
+ calc(50% - var(--micl-progress-radius) * cos(calc(var(--micl-progress-sweep) + #{$circ-gap}))),
592
+ calc(50% - var(--micl-progress-radius) * sin(#{$circ-gap}))
593
+ calc(50% - var(--micl-progress-radius) * cos(#{$circ-gap})),
594
+ 0 0;
595
+ background-size: var(--_thickness) var(--_thickness), var(--_thickness) var(--_thickness), 100% 100%;
596
+ }
597
+ &::after {
598
+ --micl-progress-active-color: #{$circ-active};
209
599
 
210
- //
211
- // Right-to-left: mirror the linear sweep direction.
212
- //
213
- [dir=rtl] progress.micl-progress-linear {
214
- transform: scaleX(-1);
215
- }
600
+ opacity: calc(1 - var(--micl-progress-amplitude));
601
+ transition: opacity motion.$md-sys-motion-duration-long2 motion.$md-sys-motion-easing-standard;
602
+ background-image: $circ-cap-active, $circ-cap-active,
603
+ conic-gradient(var(--micl-progress-active-color) 0 var(--micl-progress-sweep), transparent 0);
604
+ background-position: 50% calc(50% - var(--micl-progress-radius)),
605
+ calc(50% + var(--micl-progress-radius) * sin(var(--micl-progress-sweep)))
606
+ calc(50% - var(--micl-progress-radius) * cos(var(--micl-progress-sweep))),
607
+ 0 0;
608
+ background-size: var(--_thickness) var(--_thickness), var(--_thickness) var(--_thickness), 100% 100%;
609
+ }
610
+ .micl-circular-progress__wave {
611
+ position: absolute;
612
+ inset: 0;
613
+ opacity: var(--micl-progress-amplitude);
614
+ transition: opacity motion.$md-sys-motion-duration-long2 motion.$md-sys-motion-easing-standard;
615
+ mask-image: $wave-ring;
616
+ mask-size: 100% 100%;
216
617
 
217
- //
218
- // Honour reduced-motion: stop the only two animated (loading) states.
219
- //
220
- @media (prefers-reduced-motion: reduce) {
221
- progress.micl-progress-linear:indeterminate,
222
- progress.micl-progress-circular:indeterminate {
223
- animation: none;
618
+ &::before {
619
+ --micl-progress-sweep: calc(var(--micl-progress-fraction) * 360deg);
620
+ --micl-progress-radius: calc(var(--_box) * 0.375);
621
+ --micl-progress-thickness: var(--_thickness);
622
+ --micl-progress-active-color: #{$circ-active};
623
+
624
+ content: "";
625
+ position: absolute;
626
+ inset: 0;
627
+ background-repeat: no-repeat;
628
+ background-image: $circ-cap-active, $circ-cap-active,
629
+ conic-gradient(var(--micl-progress-active-color) 0 var(--micl-progress-sweep), transparent 0);
630
+ background-position: 50% calc(50% - var(--micl-progress-radius)),
631
+ calc(50% + #{$wave-cap-r} * sin(var(--micl-progress-sweep)))
632
+ calc(50% - #{$wave-cap-r} * cos(var(--micl-progress-sweep))),
633
+ 0 0;
634
+ background-size: var(--_thickness) var(--_thickness), var(--_thickness) var(--_thickness), 100% 100%;
635
+ }
636
+ }
637
+ &.micl-circular-progress--indeterminate {
638
+ --micl-progress-amplitude: 1;
639
+
640
+ animation: circglobal 6000ms linear infinite,
641
+ circstep 6000ms linear infinite;
642
+
643
+ &::before {
644
+ animation: circsweep 6000ms infinite;
645
+ }
646
+ &::after {
647
+ animation: circsweep 6000ms infinite;
648
+ }
649
+ .micl-circular-progress__wave {
650
+ animation: circcrawl 8000ms linear infinite;
651
+
652
+ &::before {
653
+ animation: circsweep 6000ms infinite,
654
+ circcrawlcounter 8000ms linear infinite;
655
+ }
656
+
657
+ @media (prefers-reduced-motion: reduce) {
658
+ animation-play-state: paused;
659
+
660
+ &::before {
661
+ animation-play-state: running, paused;
662
+ }
663
+ }
664
+ }
665
+ }
666
+ }
667
+ @keyframes circcrawl {
668
+ to { rotate: -360deg; }
669
+ }
670
+ @keyframes circcrawlcounter {
671
+ to {
672
+ rotate: 360deg;
673
+ --micl-progress-crawl: 360deg;
224
674
  }
225
675
  }