@expressivecss/expressive 0.12.0 → 0.14.1

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 (258) hide show
  1. package/CHANGELOG.md +339 -1
  2. package/README.md +38 -1
  3. package/dist/css/expressive.css +5342 -105
  4. package/dist/css/expressive.css.map +1 -1
  5. package/dist/css/expressive.min.css +1 -1
  6. package/dist/css/expressive.min.css.map +1 -1
  7. package/dist/fonts/material-symbols-outlined.woff2 +0 -0
  8. package/dist/fonts/material-symbols-rounded.woff2 +0 -0
  9. package/dist/fonts/material-symbols-sharp.woff2 +0 -0
  10. package/dist/js/chunks/chunk-3DHK5CZU.mjs +105 -0
  11. package/dist/js/chunks/chunk-3DHK5CZU.mjs.map +7 -0
  12. package/dist/js/chunks/{chunk-HB6IW7QQ.mjs → chunk-3GVFZ4XO.mjs} +3 -3
  13. package/dist/js/chunks/{chunk-HLDXZ7XB.mjs → chunk-4HZMB7LI.mjs} +22 -8
  14. package/dist/js/chunks/chunk-4HZMB7LI.mjs.map +7 -0
  15. package/dist/js/chunks/chunk-4KMNFIFZ.mjs +270 -0
  16. package/dist/js/chunks/chunk-4KMNFIFZ.mjs.map +7 -0
  17. package/dist/js/chunks/chunk-4TKTLGEM.mjs +262 -0
  18. package/dist/js/chunks/chunk-4TKTLGEM.mjs.map +7 -0
  19. package/dist/js/chunks/{chunk-3VOK6J7U.mjs → chunk-5BKHWHYY.mjs} +13 -6
  20. package/dist/js/chunks/chunk-5BKHWHYY.mjs.map +7 -0
  21. package/dist/js/chunks/{chunk-H2WA4XHH.mjs → chunk-5HQSGDZ5.mjs} +16 -7
  22. package/dist/js/chunks/chunk-5HQSGDZ5.mjs.map +7 -0
  23. package/dist/js/chunks/{chunk-LWBQIX5J.mjs → chunk-A7ALMYUR.mjs} +41 -44
  24. package/dist/js/chunks/chunk-A7ALMYUR.mjs.map +7 -0
  25. package/dist/js/chunks/chunk-BG6ZRB5H.mjs +154 -0
  26. package/dist/js/chunks/chunk-BG6ZRB5H.mjs.map +7 -0
  27. package/dist/js/chunks/{chunk-DLWYKFEI.mjs → chunk-CUQPB25U.mjs} +3 -3
  28. package/dist/js/chunks/{chunk-6WLSDZ4O.mjs → chunk-DAIU5SLG.mjs} +2 -2
  29. package/dist/js/chunks/chunk-FS7XY3HT.mjs +124 -0
  30. package/dist/js/chunks/chunk-FS7XY3HT.mjs.map +7 -0
  31. package/dist/js/chunks/{chunk-WJXDBPXQ.mjs → chunk-GIW4K4SE.mjs} +8 -12
  32. package/dist/js/chunks/chunk-GIW4K4SE.mjs.map +7 -0
  33. package/dist/js/chunks/chunk-GUB3TNO2.mjs +164 -0
  34. package/dist/js/chunks/chunk-GUB3TNO2.mjs.map +7 -0
  35. package/dist/js/chunks/chunk-GVGT6MIU.mjs +47 -0
  36. package/dist/js/chunks/chunk-GVGT6MIU.mjs.map +7 -0
  37. package/dist/js/chunks/{chunk-HNFSMIBY.mjs → chunk-GZKEFWPM.mjs} +83 -22
  38. package/dist/js/chunks/chunk-GZKEFWPM.mjs.map +7 -0
  39. package/dist/js/chunks/chunk-HKT2S7VM.mjs +48 -0
  40. package/dist/js/chunks/chunk-HKT2S7VM.mjs.map +7 -0
  41. package/dist/js/chunks/chunk-ILP3PDTL.mjs +187 -0
  42. package/dist/js/chunks/chunk-ILP3PDTL.mjs.map +7 -0
  43. package/dist/js/chunks/{chunk-YSBCHYXP.mjs → chunk-JIDMQGK6.mjs} +118 -13
  44. package/dist/js/chunks/chunk-JIDMQGK6.mjs.map +7 -0
  45. package/dist/js/chunks/chunk-KBNN3QDH.mjs +7 -0
  46. package/dist/js/chunks/chunk-KBNN3QDH.mjs.map +7 -0
  47. package/dist/js/chunks/{chunk-NNYP33NB.mjs → chunk-KHV6DZXX.mjs} +5 -4
  48. package/dist/js/chunks/chunk-KHV6DZXX.mjs.map +7 -0
  49. package/dist/js/chunks/{chunk-RFZZCYVU.mjs → chunk-KY6U46SM.mjs} +3 -3
  50. package/dist/js/chunks/{chunk-CKQP6P76.mjs → chunk-LRZMJZ3T.mjs} +4 -3
  51. package/dist/js/chunks/chunk-LRZMJZ3T.mjs.map +7 -0
  52. package/dist/js/chunks/{chunk-6OMRGML6.mjs → chunk-MNPROCZF.mjs} +4 -4
  53. package/dist/js/chunks/{chunk-6OMRGML6.mjs.map → chunk-MNPROCZF.mjs.map} +2 -2
  54. package/dist/js/chunks/{chunk-QV2JAWIZ.mjs → chunk-MZ6Z24BX.mjs} +3 -2
  55. package/dist/js/chunks/{chunk-QV2JAWIZ.mjs.map → chunk-MZ6Z24BX.mjs.map} +2 -2
  56. package/dist/js/chunks/chunk-NS2UMNZV.mjs +292 -0
  57. package/dist/js/chunks/chunk-NS2UMNZV.mjs.map +7 -0
  58. package/dist/js/chunks/chunk-O5XPWXIQ.mjs +406 -0
  59. package/dist/js/chunks/chunk-O5XPWXIQ.mjs.map +7 -0
  60. package/dist/js/chunks/{chunk-UBLRRJ7N.mjs → chunk-PM655FXL.mjs} +2 -2
  61. package/dist/js/chunks/{chunk-IFXVDDDH.mjs → chunk-QERLECVU.mjs} +3 -3
  62. package/dist/js/chunks/{chunk-GZWPXXY6.mjs → chunk-QJABDLSD.mjs} +5 -2
  63. package/dist/js/chunks/chunk-QJABDLSD.mjs.map +7 -0
  64. package/dist/js/chunks/chunk-RHRQKTTX.mjs +139 -0
  65. package/dist/js/chunks/chunk-RHRQKTTX.mjs.map +7 -0
  66. package/dist/js/chunks/{chunk-UNEMYWEW.mjs → chunk-S3XDFGSZ.mjs} +2 -2
  67. package/dist/js/chunks/chunk-SPETGK25.mjs +59 -0
  68. package/dist/js/chunks/chunk-SPETGK25.mjs.map +7 -0
  69. package/dist/js/chunks/chunk-TBM3FT7G.mjs +398 -0
  70. package/dist/js/chunks/chunk-TBM3FT7G.mjs.map +7 -0
  71. package/dist/js/chunks/chunk-UEXCIMJZ.mjs +214 -0
  72. package/dist/js/chunks/chunk-UEXCIMJZ.mjs.map +7 -0
  73. package/dist/js/chunks/chunk-VGZSAFTX.mjs +173 -0
  74. package/dist/js/chunks/chunk-VGZSAFTX.mjs.map +7 -0
  75. package/dist/js/chunks/{chunk-UAEAQBRC.mjs → chunk-X7OCHZVF.mjs} +2 -2
  76. package/dist/js/chunks/{chunk-EC63CHXU.mjs → chunk-YMSXJON6.mjs} +7 -6
  77. package/dist/js/chunks/chunk-YMSXJON6.mjs.map +7 -0
  78. package/dist/js/chunks/{chunk-QVVEWBOF.mjs → chunk-Z2NRKI7R.mjs} +2 -2
  79. package/dist/js/chunks/{chunk-PIJ2TAR3.mjs → chunk-ZAS25YFD.mjs} +2 -2
  80. package/dist/js/chunks/chunk-ZKZKNSLC.mjs +1 -0
  81. package/dist/js/expressive.cjs +3113 -148
  82. package/dist/js/expressive.cjs.map +4 -4
  83. package/dist/js/expressive.js +3113 -148
  84. package/dist/js/expressive.js.map +4 -4
  85. package/dist/js/expressive.min.js +11 -11
  86. package/dist/js/expressive.min.js.map +4 -4
  87. package/dist/js/expressive.mjs +95 -35
  88. package/dist/js/expressive.mjs.map +1 -1
  89. package/dist/js/internal/behaviors/bottomSheets.mjs +3 -3
  90. package/dist/js/internal/behaviors/dialogs.mjs +2 -2
  91. package/dist/js/internal/behaviors/forms.mjs +2 -2
  92. package/dist/js/internal/behaviors/sheetDrag.mjs +2 -2
  93. package/dist/js/internal/behaviors/sideSheets.mjs +3 -3
  94. package/dist/js/internal/components/autocomplete.mjs +3 -3
  95. package/dist/js/internal/components/barChart.mjs +10 -0
  96. package/dist/js/internal/components/barChart.mjs.map +7 -0
  97. package/dist/js/internal/components/buttons.mjs +2 -2
  98. package/dist/js/internal/components/cards.mjs +2 -2
  99. package/dist/js/internal/components/carousel.mjs +2 -2
  100. package/dist/js/internal/components/chips.mjs +4 -4
  101. package/dist/js/internal/components/columnChart.mjs +9 -0
  102. package/dist/js/internal/components/columnChart.mjs.map +7 -0
  103. package/dist/js/internal/components/commandPalette.mjs +9 -0
  104. package/dist/js/internal/components/commandPalette.mjs.map +7 -0
  105. package/dist/js/internal/components/confetti.mjs +8 -0
  106. package/dist/js/internal/components/confetti.mjs.map +7 -0
  107. package/dist/js/internal/components/datepicker.mjs +5 -5
  108. package/dist/js/internal/components/expandingCard.mjs +2 -2
  109. package/dist/js/internal/components/heatmapChart.mjs +9 -0
  110. package/dist/js/internal/components/heatmapChart.mjs.map +7 -0
  111. package/dist/js/internal/components/index.mjs +88 -28
  112. package/dist/js/internal/components/lightbox.mjs +2 -2
  113. package/dist/js/internal/components/lineChart.mjs +12 -0
  114. package/dist/js/internal/components/lineChart.mjs.map +7 -0
  115. package/dist/js/internal/components/mapView.mjs +9 -0
  116. package/dist/js/internal/components/mapView.mjs.map +7 -0
  117. package/dist/js/internal/components/menu.mjs +2 -2
  118. package/dist/js/internal/components/messageScroller.mjs +9 -0
  119. package/dist/js/internal/components/messageScroller.mjs.map +7 -0
  120. package/dist/js/internal/components/mixedChart.mjs +10 -0
  121. package/dist/js/internal/components/mixedChart.mjs.map +7 -0
  122. package/dist/js/internal/components/particles.mjs +8 -0
  123. package/dist/js/internal/components/particles.mjs.map +7 -0
  124. package/dist/js/internal/components/pieChart.mjs +9 -0
  125. package/dist/js/internal/components/pieChart.mjs.map +7 -0
  126. package/dist/js/internal/components/questionnaire.mjs +9 -0
  127. package/dist/js/internal/components/questionnaire.mjs.map +7 -0
  128. package/dist/js/internal/components/radarChart.mjs +9 -0
  129. package/dist/js/internal/components/radarChart.mjs.map +7 -0
  130. package/dist/js/internal/components/radialChart.mjs +9 -0
  131. package/dist/js/internal/components/radialChart.mjs.map +7 -0
  132. package/dist/js/internal/components/registry.mjs +35 -20
  133. package/dist/js/internal/components/richTextEditor.mjs +9 -0
  134. package/dist/js/internal/components/richTextEditor.mjs.map +7 -0
  135. package/dist/js/internal/components/scrollspy.mjs +1 -1
  136. package/dist/js/internal/components/select.mjs +3 -3
  137. package/dist/js/internal/components/slider.mjs +2 -2
  138. package/dist/js/internal/components/snackbar.mjs +2 -2
  139. package/dist/js/internal/components/tabs.mjs +3 -3
  140. package/dist/js/internal/components/timepicker.mjs +3 -3
  141. package/dist/js/internal/components/tooltip.mjs +2 -2
  142. package/dist/js/internal/core/utils.mjs +1 -1
  143. package/dist/js/internal/plugins/dockedDisplayPlugin.mjs +2 -2
  144. package/dist/js/modular.mjs +95 -35
  145. package/dist/types/behaviors/forms.d.ts +27 -0
  146. package/dist/types/components/barChart.d.ts +24 -0
  147. package/dist/types/components/carousel.d.ts +2 -0
  148. package/dist/types/components/columnChart.d.ts +21 -0
  149. package/dist/types/components/commandPalette.d.ts +96 -0
  150. package/dist/types/components/confetti.d.ts +103 -0
  151. package/dist/types/components/datepicker.d.ts +2 -0
  152. package/dist/types/components/heatmapChart.d.ts +49 -0
  153. package/dist/types/components/index.d.ts +15 -0
  154. package/dist/types/components/lineChart.d.ts +134 -0
  155. package/dist/types/components/mapView.d.ts +151 -0
  156. package/dist/types/components/menu.d.ts +31 -0
  157. package/dist/types/components/messageScroller.d.ts +111 -0
  158. package/dist/types/components/mixedChart.d.ts +25 -0
  159. package/dist/types/components/particles.d.ts +72 -0
  160. package/dist/types/components/pieChart.d.ts +43 -0
  161. package/dist/types/components/questionnaire.d.ts +96 -0
  162. package/dist/types/components/radarChart.d.ts +39 -0
  163. package/dist/types/components/radialChart.d.ts +45 -0
  164. package/dist/types/components/registry.d.ts +52 -0
  165. package/dist/types/components/richTextEditor.d.ts +71 -0
  166. package/dist/types/components/slider.d.ts +1 -1
  167. package/dist/types/components/snackbar.d.ts +2 -0
  168. package/dist/types/components/tabs.d.ts +1 -1
  169. package/dist/types/modular.d.ts +10 -1
  170. package/dist/types/plugins/dockedDisplayPlugin.d.ts +3 -3
  171. package/package.json +5 -1
  172. package/src/sass/README.md +3 -6
  173. package/src/sass/abstracts/_index.scss +1 -1
  174. package/src/sass/abstracts/_mixins.scss +226 -0
  175. package/src/sass/abstracts/_variables.scss +14 -0
  176. package/src/sass/base/_typography.scss +45 -0
  177. package/src/sass/components/_accordion.scss +161 -0
  178. package/src/sass/components/_aura.scss +119 -0
  179. package/src/sass/components/_avatar.scss +86 -0
  180. package/src/sass/components/_bar-chart.scss +285 -0
  181. package/src/sass/components/_bottom-sheet.scss +1 -0
  182. package/src/sass/components/_button-groups.scss +13 -3
  183. package/src/sass/components/_buttons.scss +1 -1
  184. package/src/sass/components/_cards.scss +16 -13
  185. package/src/sass/components/_column-chart.scss +134 -0
  186. package/src/sass/components/_command-palette.scss +140 -0
  187. package/src/sass/components/_confetti.scss +14 -0
  188. package/src/sass/components/_countdown.scss +89 -0
  189. package/src/sass/components/_data-table.scss +188 -0
  190. package/src/sass/components/_dialog.scss +1 -0
  191. package/src/sass/components/_empty-state.scss +78 -0
  192. package/src/sass/components/_expanding-card.scss +3 -0
  193. package/src/sass/components/_heatmap-chart.scss +156 -0
  194. package/src/sass/components/_index.scss +30 -0
  195. package/src/sass/components/_kpi.scss +162 -0
  196. package/src/sass/components/_line-chart.scss +102 -0
  197. package/src/sass/components/_map.scss +188 -0
  198. package/src/sass/components/_marquee.scss +111 -0
  199. package/src/sass/components/_menu.scss +10 -0
  200. package/src/sass/components/_message-scroller.scss +66 -0
  201. package/src/sass/components/_message.scss +202 -0
  202. package/src/sass/components/_mixed-chart.scss +157 -0
  203. package/src/sass/components/_navigation-bar.scss +1 -0
  204. package/src/sass/components/_navigation-rail.scss +9 -0
  205. package/src/sass/components/_particles.scss +14 -0
  206. package/src/sass/components/_pie-chart.scss +203 -0
  207. package/src/sass/components/_popover.scss +112 -0
  208. package/src/sass/components/_questionnaire.scss +144 -0
  209. package/src/sass/components/_radar-chart.scss +205 -0
  210. package/src/sass/components/_radial-chart.scss +174 -0
  211. package/src/sass/components/_rich-text-editor.scss +99 -0
  212. package/src/sass/components/_search.scss +1 -0
  213. package/src/sass/components/_side-sheet.scss +1 -0
  214. package/src/sass/components/_skeleton.scss +81 -0
  215. package/src/sass/components/_snackbar.scss +1 -0
  216. package/src/sass/components/_stat.scss +86 -0
  217. package/src/sass/components/_stepper.scss +190 -0
  218. package/src/sass/components/_table_of_contents.scss +3 -1
  219. package/src/sass/components/_timeline.scss +114 -0
  220. package/src/sass/components/_toolbar.scss +1 -0
  221. package/src/sass/components/_tooltip.scss +2 -0
  222. package/src/sass/components/_tree.scss +139 -0
  223. package/src/sass/components/forms/_checkboxes.scss +7 -2
  224. package/src/sass/components/forms/_drop-zone.scss +128 -0
  225. package/src/sass/components/forms/_index.scss +2 -0
  226. package/src/sass/components/forms/_input-fields.scss +133 -2
  227. package/src/sass/components/forms/_rating.scss +165 -0
  228. package/src/sass/tokens/_reference.scss +3 -15
  229. package/src/sass/utilities/_index.scss +2 -0
  230. package/src/sass/utilities/_scroll-area.scss +35 -0
  231. package/src/sass/utilities/_shapes.scss +164 -0
  232. package/dist/js/chunks/chunk-3VOK6J7U.mjs.map +0 -7
  233. package/dist/js/chunks/chunk-CKQP6P76.mjs.map +0 -7
  234. package/dist/js/chunks/chunk-EC63CHXU.mjs.map +0 -7
  235. package/dist/js/chunks/chunk-G3I5H2U3.mjs +0 -7
  236. package/dist/js/chunks/chunk-G3I5H2U3.mjs.map +0 -7
  237. package/dist/js/chunks/chunk-GZWPXXY6.mjs.map +0 -7
  238. package/dist/js/chunks/chunk-H2WA4XHH.mjs.map +0 -7
  239. package/dist/js/chunks/chunk-HLDXZ7XB.mjs.map +0 -7
  240. package/dist/js/chunks/chunk-HNFSMIBY.mjs.map +0 -7
  241. package/dist/js/chunks/chunk-LWBQIX5J.mjs.map +0 -7
  242. package/dist/js/chunks/chunk-NNYP33NB.mjs.map +0 -7
  243. package/dist/js/chunks/chunk-PSSHQWCX.mjs +0 -100
  244. package/dist/js/chunks/chunk-PSSHQWCX.mjs.map +0 -7
  245. package/dist/js/chunks/chunk-WJXDBPXQ.mjs.map +0 -7
  246. package/dist/js/chunks/chunk-WWPAPHMA.mjs +0 -1
  247. package/dist/js/chunks/chunk-YSBCHYXP.mjs.map +0 -7
  248. /package/dist/js/chunks/{chunk-HB6IW7QQ.mjs.map → chunk-3GVFZ4XO.mjs.map} +0 -0
  249. /package/dist/js/chunks/{chunk-DLWYKFEI.mjs.map → chunk-CUQPB25U.mjs.map} +0 -0
  250. /package/dist/js/chunks/{chunk-6WLSDZ4O.mjs.map → chunk-DAIU5SLG.mjs.map} +0 -0
  251. /package/dist/js/chunks/{chunk-RFZZCYVU.mjs.map → chunk-KY6U46SM.mjs.map} +0 -0
  252. /package/dist/js/chunks/{chunk-UBLRRJ7N.mjs.map → chunk-PM655FXL.mjs.map} +0 -0
  253. /package/dist/js/chunks/{chunk-IFXVDDDH.mjs.map → chunk-QERLECVU.mjs.map} +0 -0
  254. /package/dist/js/chunks/{chunk-UNEMYWEW.mjs.map → chunk-S3XDFGSZ.mjs.map} +0 -0
  255. /package/dist/js/chunks/{chunk-UAEAQBRC.mjs.map → chunk-X7OCHZVF.mjs.map} +0 -0
  256. /package/dist/js/chunks/{chunk-QVVEWBOF.mjs.map → chunk-Z2NRKI7R.mjs.map} +0 -0
  257. /package/dist/js/chunks/{chunk-PIJ2TAR3.mjs.map → chunk-ZAS25YFD.mjs.map} +0 -0
  258. /package/dist/js/chunks/{chunk-WWPAPHMA.mjs.map → chunk-ZKZKNSLC.mjs.map} +0 -0
@@ -0,0 +1,139 @@
1
+ @use "../abstracts" as *;
2
+
3
+ // Tree. A <ul class="tree"> of nested lists, for file browsers and deep
4
+ // navigation. A branch is an <li> holding a <details>: its <summary> is the
5
+ // row and its nested <ul> the children. A leaf is an <li> holding a link or
6
+ // a span. aria-current marks the selected row.
7
+ //
8
+ // It is a set of disclosures and links, not role="tree": every row is a Tab
9
+ // stop and the browser owns opening a branch. A tree role would promise
10
+ // arrow-key navigation that native disclosures do not provide.
11
+ //
12
+ // Tokens:
13
+ // --md-comp-tree-row-height 40px
14
+ // --md-comp-tree-row-shape 100px (pill)
15
+ // --md-comp-tree-guide-color outline-variant
16
+ // --md-comp-tree-selected-container-color secondary-container
17
+
18
+ $_tree-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 15.4 6 9.4 7.4 8l4.6 4.6L16.6 8 18 9.4z'/%3E%3C/svg%3E");
19
+
20
+ .tree {
21
+ --md-comp-tree-row-height: 40px;
22
+ --md-comp-tree-row-shape: 100px;
23
+ --md-comp-tree-guide-color: var(--md-sys-color-outline-variant);
24
+ --md-comp-tree-selected-container-color: var(--md-sys-color-secondary-container);
25
+
26
+ margin: $element-top-margin 0 $element-bottom-margin;
27
+ padding: 0;
28
+ list-style: none;
29
+ color: var(--md-sys-color-on-surface-variant);
30
+
31
+ // Each level hangs a guide line from the centre of its parent's chevron
32
+ // (12px inset + half the 20px chevron) and indents past it.
33
+ ul {
34
+ margin: 0;
35
+ margin-inline-start: 22px;
36
+ padding: 0;
37
+ padding-inline-start: 6px;
38
+ border-inline-start: 1px solid var(--md-comp-tree-guide-color);
39
+ list-style: none;
40
+ }
41
+
42
+ li {
43
+ margin: 0;
44
+ }
45
+
46
+ li > :is(a, span),
47
+ li > details > summary {
48
+ box-sizing: border-box;
49
+ display: flex;
50
+ align-items: center;
51
+ gap: 8px;
52
+ min-height: var(--md-comp-tree-row-height);
53
+ padding-inline: 12px 16px;
54
+ border-radius: var(--md-comp-tree-row-shape);
55
+ color: inherit;
56
+ text-decoration: none;
57
+ @include typescale("label-large");
58
+
59
+ > #{$icon} {
60
+ flex: none;
61
+ font-size: 20px;
62
+ }
63
+ }
64
+
65
+ // A leaf lines its text up with a branch's text, after the chevron.
66
+ li > :is(a, span) {
67
+ padding-inline-start: calc(12px + 20px + 8px);
68
+ }
69
+
70
+ li > a,
71
+ li > details > summary {
72
+ cursor: pointer;
73
+ @include focus-visible;
74
+
75
+ &:hover {
76
+ background-color: color-mix(
77
+ in oklab,
78
+ var(--md-sys-color-on-surface) state-opacity("hover"),
79
+ transparent
80
+ );
81
+ }
82
+ }
83
+
84
+ li > details > summary {
85
+ list-style: none;
86
+ user-select: none;
87
+
88
+ &::-webkit-details-marker {
89
+ display: none;
90
+ }
91
+
92
+ // Points to the end edge while closed and down once open.
93
+ &::before {
94
+ content: "";
95
+ flex: none;
96
+ width: 20px;
97
+ height: 20px;
98
+ background-color: currentColor;
99
+ mask: $_tree-chevron center / 20px no-repeat;
100
+ transform: rotate(-90deg);
101
+ transition: transform 150ms ease-out;
102
+ }
103
+
104
+ &:dir(rtl)::before {
105
+ transform: rotate(90deg);
106
+ }
107
+ }
108
+
109
+ li > details[open] > summary::before {
110
+ transform: none;
111
+ }
112
+
113
+ :is(li > a, li > span, li > details > summary)[aria-current]:not([aria-current="false"]) {
114
+ background-color: var(--md-comp-tree-selected-container-color);
115
+ color: var(--md-sys-color-on-secondary-container);
116
+
117
+ > #{$icon} {
118
+ --md-icon-fill: 1;
119
+ }
120
+ }
121
+
122
+ @media (prefers-reduced-motion: reduce) {
123
+ li > details > summary::before {
124
+ transition: none;
125
+ }
126
+ }
127
+
128
+ @media (forced-colors: active) {
129
+ li > details > summary::before {
130
+ forced-color-adjust: none;
131
+ background-color: CanvasText;
132
+ }
133
+
134
+ [aria-current]:not([aria-current="false"]) {
135
+ outline: 2px solid Highlight;
136
+ outline-offset: -2px;
137
+ }
138
+ }
139
+ }
@@ -210,11 +210,16 @@ label:has(> [type="checkbox"]:disabled):not(.switch),
210
210
  // 18dp anatomy. Exclude .switch — that file paints the track on a span.
211
211
  $_cb-span: "*:not(.switch) > [type='checkbox'] + span:not(.lever, .supporting-text, .character-counter, .file-path)";
212
212
 
213
+ // inline-block, not inline-flex: a flex span turns each text run and link
214
+ // inside it into its own item, which drops the spaces around a link and
215
+ // splits "I agree to the <a>Terms</a>" into columns. The block padding
216
+ // centers one line in the 48px target, as align-items did.
213
217
  #{$_cb-span} {
214
218
  position: relative;
215
- display: inline-flex;
216
- align-items: center;
219
+ display: inline-block;
220
+ box-sizing: border-box;
217
221
  min-height: 48px;
222
+ padding-block: calc((48px - 1lh) / 2);
218
223
  padding-left: 30px;
219
224
  cursor: pointer;
220
225
  user-select: none;
@@ -0,0 +1,128 @@
1
+ @use "../../abstracts" as *;
2
+
3
+ // Drop zone. A .drop-zone is a large target for choosing files: a <label>
4
+ // holding an icon, a prompt and a native <input type="file">, with an
5
+ // optional .drop-zone-files list after it.
6
+ //
7
+ // The input is stretched invisibly over the whole label, so the browser
8
+ // takes a click, a keypress or a dropped file exactly as it does on a plain
9
+ // file input. The Forms behavior adds .dragover while files are dragged over
10
+ // it and fills .drop-zone-files with each chosen file's name and size.
11
+ //
12
+ // Tokens:
13
+ // --md-comp-drop-zone-shape 16px
14
+ // --md-comp-drop-zone-outline-color outline
15
+ // --md-comp-drop-zone-dragover-container-color primary-container
16
+ // --md-comp-drop-zone-dragover-color on-primary-container
17
+
18
+ .drop-zone {
19
+ --md-comp-drop-zone-shape: 16px;
20
+ --md-comp-drop-zone-outline-color: var(--md-sys-color-outline);
21
+ --md-comp-drop-zone-dragover-container-color: var(--md-sys-color-primary-container);
22
+ --md-comp-drop-zone-dragover-color: var(--md-sys-color-on-primary-container);
23
+
24
+ margin: $element-top-margin 0 $element-bottom-margin;
25
+
26
+ > label {
27
+ position: relative;
28
+ box-sizing: border-box;
29
+ display: flex;
30
+ flex-direction: column;
31
+ align-items: center;
32
+ gap: 4px;
33
+ padding: 32px 24px;
34
+ border: 1px dashed var(--md-comp-drop-zone-outline-color);
35
+ border-radius: var(--md-comp-drop-zone-shape);
36
+ text-align: center;
37
+ color: var(--md-sys-color-on-surface-variant);
38
+ cursor: pointer;
39
+ transition: background-color 0.2s ease-out, border-color 0.2s ease-out;
40
+ @include typescale("body-large");
41
+
42
+ > #{$icon} {
43
+ margin-block-end: 8px;
44
+ font-size: 32px;
45
+ color: var(--md-sys-color-primary);
46
+ }
47
+
48
+ > small {
49
+ @include typescale("body-small");
50
+ }
51
+
52
+ > input[type="file"] {
53
+ position: absolute;
54
+ inset: 0;
55
+ width: 100%;
56
+ height: 100%;
57
+ margin: 0;
58
+ padding: 0;
59
+ opacity: 0;
60
+ cursor: pointer;
61
+ }
62
+
63
+ &:hover {
64
+ background-color: color-mix(
65
+ in oklab,
66
+ var(--md-sys-color-on-surface) state-opacity("hover"),
67
+ transparent
68
+ );
69
+ }
70
+
71
+ &:has(> input:focus-visible) {
72
+ @include focus-ring;
73
+ }
74
+
75
+ &:has(> input:disabled) {
76
+ opacity: 0.38;
77
+ cursor: default;
78
+ pointer-events: none;
79
+ }
80
+ }
81
+
82
+ &.dragover > label {
83
+ border-style: solid;
84
+ border-color: var(--md-sys-color-primary);
85
+ background-color: var(--md-comp-drop-zone-dragover-container-color);
86
+ color: var(--md-comp-drop-zone-dragover-color);
87
+ }
88
+
89
+ > .drop-zone-files {
90
+ display: flex;
91
+ flex-direction: column;
92
+ gap: 2px;
93
+ margin: 8px 0 0;
94
+ padding: 0;
95
+ list-style: none;
96
+
97
+ > li {
98
+ display: flex;
99
+ justify-content: space-between;
100
+ gap: 16px;
101
+ padding: 8px 16px;
102
+ border-radius: 8px;
103
+ background-color: var(--md-sys-color-surface-container);
104
+ color: var(--md-sys-color-on-surface);
105
+ @include typescale("body-medium");
106
+
107
+ > :first-child {
108
+ min-width: 0;
109
+ overflow-wrap: anywhere;
110
+ }
111
+
112
+ > :last-child:not(:first-child) {
113
+ flex: none;
114
+ color: var(--md-sys-color-on-surface-variant);
115
+ }
116
+ }
117
+
118
+ &:empty {
119
+ display: none;
120
+ }
121
+ }
122
+ }
123
+
124
+ @media (prefers-reduced-motion: reduce) {
125
+ .drop-zone > label {
126
+ transition: none;
127
+ }
128
+ }
@@ -1,9 +1,11 @@
1
1
  @forward 'input-fields';
2
2
  @forward 'radio-buttons';
3
+ @forward 'rating';
3
4
  @forward 'checkboxes';
4
5
  @forward 'switches';
5
6
  @forward 'select';
6
7
  @forward 'file-input';
8
+ @forward 'drop-zone';
7
9
  @forward 'slider';
8
10
  @forward 'fieldset';
9
11
 
@@ -177,7 +177,7 @@ $_not-label: ".supporting-text, .character-counter, .file-path, .caret, .prefix,
177
177
  // .character-counter, .file-path). So the documented markup names the side
178
178
  // explicitly with .prefix / .suffix, and those rules key on nothing else.
179
179
  > i:is(.prefix, .suffix, :first-of-type, :last-of-type, :last-child),
180
- > :is(.prefix, .suffix) {
180
+ > :is(.prefix, .suffix):not(.icon-button) {
181
181
  position: absolute;
182
182
  top: 16px;
183
183
  display: flex;
@@ -200,7 +200,7 @@ $_not-label: ".supporting-text, .character-counter, .file-path, .caret, .prefix,
200
200
  > i.suffix,
201
201
  > i:last-of-type:not(:first-of-type),
202
202
  > i:last-child:not(:first-child):not(.prefix),
203
- > .suffix {
203
+ > .suffix:not(.icon-button) {
204
204
  right: 12px;
205
205
  // Both icons inherited this from the floating-label rule until they were
206
206
  // excluded from it. .prefix restates it below; .suffix has to as well, or
@@ -208,6 +208,15 @@ $_not-label: ".supporting-text, .character-counter, .file-path, .caret, .prefix,
208
208
  pointer-events: none;
209
209
  }
210
210
 
211
+ // A trailing icon button is a control, so it keeps its 40dp target and its
212
+ // clicks. It centres on the same point as a 24dp trailing icon.
213
+ > .icon-button.suffix {
214
+ position: absolute;
215
+ top: 8px;
216
+ right: 4px;
217
+ z-index: 1;
218
+ }
219
+
211
220
  &:has(> i:first-of-type:not(.suffix):not(:last-child), > i.prefix, > .prefix) {
212
221
  > :is(input, textarea) {
213
222
  padding-left: 52px;
@@ -351,3 +360,125 @@ textarea {
351
360
  }
352
361
  }
353
362
  }
363
+
364
+ // Password visibility toggle. A trailing .icon-button.password-toggle with
365
+ // aria-pressed holds two icons: the first shows while the password is hidden,
366
+ // the second once it is shown. The Forms behavior flips the input's type.
367
+ .password-toggle {
368
+ > #{$icon}:last-child:not(:first-child) {
369
+ display: none;
370
+ }
371
+
372
+ &[aria-pressed="true"] {
373
+ > #{$icon}:first-child:not(:last-child) {
374
+ display: none;
375
+ }
376
+
377
+ > #{$icon}:last-child:not(:first-child) {
378
+ display: inline-block;
379
+ }
380
+ }
381
+ }
382
+
383
+ // One-time code. A single native input drawn as a row of cells, so paste,
384
+ // autofill from autocomplete="one-time-code", undo and the caret all stay the
385
+ // browser's. A monospace face makes every digit 1ch wide; letter-spacing
386
+ // moves each one to the next cell, and the input is clipped after the last.
387
+ //
388
+ // Tokens:
389
+ // --md-comp-otp-length 6
390
+ // --md-comp-otp-cell-width 48px
391
+ // --md-comp-otp-cell-height 56px
392
+ // --md-comp-otp-gap 8px
393
+ // --md-comp-otp-cell-color surface-container-highest
394
+ // --md-comp-otp-indicator-color on-surface-variant / focus: primary
395
+ //
396
+ // :not(.browser-default) matches the weight of the shared text-input rule
397
+ // above, which would otherwise win on width, height and letter-spacing.
398
+ input.otp:not(.browser-default) {
399
+ --md-comp-otp-length: 6;
400
+ --md-comp-otp-cell-width: 48px;
401
+ --md-comp-otp-cell-height: 56px;
402
+ --md-comp-otp-gap: 8px;
403
+ --md-comp-otp-cell-color: var(--md-sys-color-surface-container-highest);
404
+ --md-comp-otp-indicator-color: var(--md-sys-color-on-surface-variant);
405
+ // Derived, not for overriding: the distance between cell starts, the
406
+ // inset that centres a digit in its cell, and the box past the last cell
407
+ // that the caret needs and the clip hides.
408
+ --md-comp-otp-pitch: calc(var(--md-comp-otp-cell-width) + var(--md-comp-otp-gap));
409
+ --md-comp-otp-inset: calc((var(--md-comp-otp-cell-width) - 1ch) / 2);
410
+ --md-comp-otp-overhang: calc(var(--md-comp-otp-gap) + var(--md-comp-otp-inset) + 2px);
411
+
412
+ box-sizing: border-box;
413
+ display: block;
414
+ // Room for the caret after the last digit, clipped back to the cells; the
415
+ // negative margin gives the overhang back to the layout.
416
+ width: calc(var(--md-comp-otp-length) * var(--md-comp-otp-pitch) + var(--md-comp-otp-inset) + 2px);
417
+ height: var(--md-comp-otp-cell-height);
418
+ margin: 0 calc(var(--md-comp-otp-overhang) * -1) 0 0;
419
+ padding: 0 0 0 var(--md-comp-otp-inset);
420
+ border: 0;
421
+ border-radius: 0;
422
+ outline: 0;
423
+ box-shadow: none;
424
+ clip-path: inset(0 var(--md-comp-otp-overhang) 0 0);
425
+ // Digits read left to right in every script.
426
+ direction: ltr;
427
+ font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace;
428
+ font-size: 24px;
429
+ font-variant-numeric: tabular-nums;
430
+ letter-spacing: calc(var(--md-comp-otp-pitch) - 1ch);
431
+ color: var(--md-sys-color-on-surface);
432
+ caret-color: var(--md-sys-color-primary);
433
+ background-color: transparent;
434
+ background-image:
435
+ linear-gradient(
436
+ to right,
437
+ var(--md-comp-otp-indicator-color) var(--md-comp-otp-cell-width),
438
+ transparent 0
439
+ ),
440
+ linear-gradient(
441
+ to right,
442
+ var(--md-comp-otp-cell-color) var(--md-comp-otp-cell-width),
443
+ transparent 0
444
+ );
445
+ background-size:
446
+ var(--md-comp-otp-pitch) 1px,
447
+ var(--md-comp-otp-pitch) 100%;
448
+ background-position: left bottom, left top;
449
+ background-repeat: repeat-x;
450
+
451
+ &::placeholder {
452
+ color: var(--md-sys-color-on-surface-variant);
453
+ opacity: 1;
454
+ }
455
+
456
+ // Every cell's indicator turns primary and thickens while the code has
457
+ // focus; the clip would cut an outline, so this is the focus ring.
458
+ &:focus,
459
+ &:focus-visible {
460
+ --md-comp-otp-indicator-color: var(--md-sys-color-primary);
461
+
462
+ outline: 0;
463
+ background-size:
464
+ var(--md-comp-otp-pitch) 2px,
465
+ var(--md-comp-otp-pitch) 100%;
466
+ }
467
+
468
+ &.invalid,
469
+ &[aria-invalid="true"] {
470
+ --md-comp-otp-indicator-color: var(--md-sys-color-error);
471
+ }
472
+
473
+ &:disabled {
474
+ opacity: 0.38;
475
+ }
476
+
477
+ @media (forced-colors: active) {
478
+ --md-comp-otp-indicator-color: CanvasText;
479
+
480
+ &:focus {
481
+ --md-comp-otp-indicator-color: Highlight;
482
+ }
483
+ }
484
+ }
@@ -0,0 +1,165 @@
1
+ @use "../../abstracts" as *;
2
+
3
+ // Rating. Two forms share the star.
4
+ //
5
+ // Input: a <fieldset class="rating"> with a <legend> and one radio per star,
6
+ // each in a <label> whose visually hidden text ("3 stars") comes before the
7
+ // radio: a span after it is the older input + span radio, which hides the
8
+ // input. The radio itself is drawn as the star, so arrow keys, form
9
+ // submission and the group's name stay native. A star fills when it or a
10
+ // later star is checked; hovering previews.
11
+ //
12
+ // Display: <span class="rating" role="img" aria-label="Rated 4.5 out of 5">
13
+ // with --md-comp-rating-value. The stars fill to that value, halves included.
14
+ //
15
+ // Loaded after radio-buttons: the input rules match the radio rules' weight
16
+ // and win on order.
17
+ //
18
+ // Tokens:
19
+ // --md-comp-rating-size 24px (display 20px)
20
+ // --md-comp-rating-color tertiary
21
+ // --md-comp-rating-empty-color outline-variant
22
+ // --md-comp-rating-value 0 (display)
23
+ // --md-comp-rating-max 5 (display)
24
+
25
+ $_rating-star: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m12 17.27 6.18 3.73-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z'/%3E%3C/svg%3E");
26
+
27
+ .rating {
28
+ --md-comp-rating-size: 24px;
29
+ --md-comp-rating-color: var(--md-sys-color-tertiary);
30
+ --md-comp-rating-empty-color: var(--md-sys-color-outline-variant);
31
+ }
32
+
33
+ fieldset.rating {
34
+ display: flex;
35
+ flex-wrap: wrap;
36
+ align-items: center;
37
+ margin: 0;
38
+ padding: 0;
39
+ border: 0;
40
+
41
+ > legend {
42
+ margin-block-end: 4px;
43
+ padding: 0;
44
+ color: var(--md-sys-color-on-surface-variant);
45
+ @include typescale("body-medium");
46
+ }
47
+
48
+ > label {
49
+ display: inline-flex;
50
+ gap: 0;
51
+ min-height: 0;
52
+ padding: 4px;
53
+ border-radius: 50%;
54
+ cursor: pointer;
55
+
56
+ &:has(> input:focus-visible) {
57
+ @include focus-ring;
58
+ }
59
+
60
+ &:has(> input:disabled) {
61
+ opacity: 0.38;
62
+ cursor: default;
63
+ }
64
+ }
65
+
66
+ > label > [type="radio"] {
67
+ flex: none;
68
+ width: var(--md-comp-rating-size);
69
+ height: var(--md-comp-rating-size);
70
+ border: 0;
71
+ border-radius: 0;
72
+ background-color: var(--md-comp-rating-empty-color);
73
+ background-image: none;
74
+ box-shadow: none;
75
+ mask: $_rating-star center / 100% no-repeat;
76
+ outline: 0;
77
+ transition: background-color 0.15s ease-out;
78
+
79
+ // The base radio draws its dot in :checked, :hover and the disabled
80
+ // states, some at a higher weight; the star mask would show it.
81
+ &:checked,
82
+ &:hover,
83
+ &:disabled,
84
+ &:disabled:checked {
85
+ border: 0;
86
+ background-image: none;
87
+ box-shadow: none;
88
+ }
89
+ }
90
+
91
+ // Filled: the checked star and every star before it.
92
+ > label:has(> :checked) > [type="radio"],
93
+ > label:has(~ label > :checked) > [type="radio"] {
94
+ background-color: var(--md-comp-rating-color);
95
+ }
96
+
97
+ // Hovering previews the rating under the pointer. Both rules sit under the
98
+ // same :has() so the preview outranks the reset.
99
+ &:has(> label:hover) {
100
+ > label > [type="radio"] {
101
+ background-color: var(--md-comp-rating-empty-color);
102
+ }
103
+
104
+ > label:hover > [type="radio"],
105
+ > label:has(~ label:hover) > [type="radio"] {
106
+ background-color: color-mix(in oklab, var(--md-comp-rating-color) 70%, transparent);
107
+ }
108
+ }
109
+
110
+ @media (prefers-reduced-motion: reduce) {
111
+ > label > [type="radio"] {
112
+ transition: none;
113
+ }
114
+ }
115
+ }
116
+
117
+ .rating:not(fieldset) {
118
+ --md-comp-rating-size: 20px;
119
+ --md-comp-rating-value: 0;
120
+ --md-comp-rating-max: 5;
121
+
122
+ display: inline-block;
123
+ width: calc(var(--md-comp-rating-size) * var(--md-comp-rating-max));
124
+ height: var(--md-comp-rating-size);
125
+ vertical-align: middle;
126
+ background: linear-gradient(
127
+ to right,
128
+ var(--md-comp-rating-color) calc(var(--md-comp-rating-value) / var(--md-comp-rating-max) * 100%),
129
+ var(--md-comp-rating-empty-color) 0
130
+ );
131
+ mask: $_rating-star left center / var(--md-comp-rating-size) repeat-x;
132
+
133
+ &:dir(rtl) {
134
+ background: linear-gradient(
135
+ to left,
136
+ var(--md-comp-rating-color) calc(var(--md-comp-rating-value) / var(--md-comp-rating-max) * 100%),
137
+ var(--md-comp-rating-empty-color) 0
138
+ );
139
+ mask-position: right center;
140
+ }
141
+ }
142
+
143
+ @media (forced-colors: active) {
144
+ fieldset.rating > label > [type="radio"],
145
+ .rating:not(fieldset) {
146
+ forced-color-adjust: none;
147
+ }
148
+
149
+ fieldset.rating > label > [type="radio"] {
150
+ background-color: GrayText;
151
+ }
152
+
153
+ fieldset.rating > label:has(> :checked) > [type="radio"],
154
+ fieldset.rating > label:has(~ label > :checked) > [type="radio"] {
155
+ background-color: Highlight;
156
+ }
157
+
158
+ .rating:not(fieldset) {
159
+ background: linear-gradient(
160
+ to right,
161
+ Highlight calc(var(--md-comp-rating-value) / var(--md-comp-rating-max) * 100%),
162
+ GrayText 0
163
+ );
164
+ }
165
+ }
@@ -24,21 +24,9 @@
24
24
  // against #006495, the one source there is ground truth for - $md-source below
25
25
  // is a branding choice and is free to change without failing it.
26
26
 
27
- // The seed every generated ramp derives from. Chosen for a restaurant POS: the
28
- // error ramp is pinned at hue 27.7deg and both primary and tertiary (source
29
- // +62deg) derive from this, so the seed has to keep both clear of red. Warm
30
- // "appetising" hues (0-60deg) are disqualified outright - they put primary on
31
- // top of error, dEok 0.07-0.12 against ~0.28 here.
32
- //
33
- // Teal wins on *worst case* across both schemes rather than on either one
34
- // alone, which is the metric that matters: evening service runs dark mode in a
35
- // dim room, and that is where a confirm/void mix-up actually happens.
36
- // light primary40 vs error40 dEok 0.278
37
- // dark primary80 vs error80 dEok 0.212 <- best of the candidates
38
- // light tertiary40 vs error40 dEok 0.224
39
- // It also leaves green free for the "settled/paid" role a POS will want and
40
- // Material does not supply.
41
- $md-source: #006A79 !default;
27
+ // Mist Iris is the default seed for the generated ramps. Primary, secondary,
28
+ // tertiary and neutral colors derive from it; the error ramp stays fixed.
29
+ $md-source: #c6a0f6 !default;
42
30
 
43
31
  // tone -> OKLCH lightness. Fitted against the reference ramps; see the test.
44
32
  $tones: (
@@ -6,3 +6,5 @@
6
6
  @forward "spacing"; // .m-3, .pt-2, .px-4, ...
7
7
  @forward "visibility"; // .hide, .hide-on-med-and-down, .show-on-large, ...
8
8
  @forward "helpers"; // alignment, floats, truncate, responsive media
9
+ @forward "scroll-area"; // native scrolling with themed scrollbars
10
+ @forward "shapes"; // .shape-pebble, .shape-scallop-6, ... (masks)
@@ -0,0 +1,35 @@
1
+ @use "../abstracts" as *;
2
+
3
+ // Keep scrolling native; use the current theme for scrollbar colors.
4
+ .scroll-area {
5
+ overflow: auto;
6
+ scrollbar-width: thin;
7
+ scrollbar-color: var(--scroll-area-thumb-color, var(--md-sys-color-on-surface-variant)) var(--scroll-area-track-color, transparent);
8
+ }
9
+
10
+ // Older WebKit engines do not implement the standard scrollbar properties.
11
+ @supports not (scrollbar-color: red blue) {
12
+ @media (forced-colors: none) {
13
+ .scroll-area::-webkit-scrollbar {
14
+ width: 8px;
15
+ height: 8px;
16
+ }
17
+
18
+ .scroll-area::-webkit-scrollbar-thumb {
19
+ background-color: var(--scroll-area-thumb-color, var(--md-sys-color-on-surface-variant));
20
+ border-radius: 999px;
21
+ }
22
+
23
+ .scroll-area::-webkit-scrollbar-track,
24
+ .scroll-area::-webkit-scrollbar-corner {
25
+ background-color: var(--scroll-area-track-color, transparent);
26
+ }
27
+ }
28
+ }
29
+
30
+ @media (forced-colors: active) {
31
+ .scroll-area {
32
+ scrollbar-width: auto;
33
+ scrollbar-color: auto;
34
+ }
35
+ }