@expressivecss/expressive 0.11.0 → 0.13.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 (265) hide show
  1. package/CHANGELOG.md +392 -7
  2. package/README.md +37 -1
  3. package/dist/css/expressive.css +5440 -234
  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-AYYYWUJ4.mjs → chunk-3CLXLPYS.mjs} +17 -11
  11. package/dist/js/chunks/chunk-3CLXLPYS.mjs.map +7 -0
  12. package/dist/js/chunks/chunk-3DHK5CZU.mjs +105 -0
  13. package/dist/js/chunks/chunk-3DHK5CZU.mjs.map +7 -0
  14. package/dist/js/chunks/{chunk-IMUPRRI6.mjs → chunk-3VOK6J7U.mjs} +3 -3
  15. package/dist/js/chunks/chunk-4PWAPV6F.mjs +7 -0
  16. package/dist/js/chunks/chunk-4PWAPV6F.mjs.map +7 -0
  17. package/dist/js/chunks/{chunk-XFJ452AZ.mjs → chunk-55IA2XUC.mjs} +5 -6
  18. package/dist/js/chunks/{chunk-XFJ452AZ.mjs.map → chunk-55IA2XUC.mjs.map} +2 -2
  19. package/dist/js/chunks/{chunk-XDB3G6RL.mjs → chunk-6N2XAEFK.mjs} +15 -4
  20. package/dist/js/chunks/{chunk-XDB3G6RL.mjs.map → chunk-6N2XAEFK.mjs.map} +2 -2
  21. package/dist/js/chunks/{chunk-MISGHDUU.mjs → chunk-6OMRGML6.mjs} +9 -7
  22. package/dist/js/chunks/{chunk-MISGHDUU.mjs.map → chunk-6OMRGML6.mjs.map} +2 -2
  23. package/dist/js/chunks/{chunk-A3BJA7V4.mjs → chunk-6WLSDZ4O.mjs} +2 -2
  24. package/dist/js/chunks/chunk-CCWDV5CR.mjs +292 -0
  25. package/dist/js/chunks/chunk-CCWDV5CR.mjs.map +7 -0
  26. package/dist/js/chunks/{chunk-JODJAGFS.mjs → chunk-CKQP6P76.mjs} +31 -8
  27. package/dist/js/chunks/chunk-CKQP6P76.mjs.map +7 -0
  28. package/dist/js/chunks/{chunk-KR44BSYQ.mjs → chunk-DLWYKFEI.mjs} +3 -3
  29. package/dist/js/chunks/chunk-DTKR54I6.mjs +270 -0
  30. package/dist/js/chunks/chunk-DTKR54I6.mjs.map +7 -0
  31. package/dist/js/chunks/{chunk-SLFNPY5M.mjs → chunk-EC63CHXU.mjs} +2 -2
  32. package/dist/js/chunks/chunk-GVGT6MIU.mjs +47 -0
  33. package/dist/js/chunks/chunk-GVGT6MIU.mjs.map +7 -0
  34. package/dist/js/chunks/{chunk-LZVBJ33S.mjs → chunk-GZWPXXY6.mjs} +15 -8
  35. package/dist/js/chunks/chunk-GZWPXXY6.mjs.map +7 -0
  36. package/dist/js/chunks/chunk-HKT2S7VM.mjs +48 -0
  37. package/dist/js/chunks/chunk-HKT2S7VM.mjs.map +7 -0
  38. package/dist/js/chunks/{chunk-D4UZ4HFN.mjs → chunk-IFXVDDDH.mjs} +23 -11
  39. package/dist/js/chunks/chunk-IFXVDDDH.mjs.map +7 -0
  40. package/dist/js/chunks/chunk-K4CJCRGE.mjs +262 -0
  41. package/dist/js/chunks/chunk-K4CJCRGE.mjs.map +7 -0
  42. package/dist/js/chunks/chunk-LNCCYGPC.mjs +163 -0
  43. package/dist/js/chunks/chunk-LNCCYGPC.mjs.map +7 -0
  44. package/dist/js/chunks/{chunk-QSQ24FYT.mjs → chunk-LTWPGFBR.mjs} +2 -2
  45. package/dist/js/chunks/{chunk-QSQ24FYT.mjs.map → chunk-LTWPGFBR.mjs.map} +2 -2
  46. package/dist/js/chunks/{chunk-I5KR22BY.mjs → chunk-LWBQIX5J.mjs} +15 -15
  47. package/dist/js/chunks/chunk-LWBQIX5J.mjs.map +7 -0
  48. package/dist/js/chunks/{chunk-GY2Z5CJ2.mjs → chunk-NNYP33NB.mjs} +67 -32
  49. package/dist/js/chunks/chunk-NNYP33NB.mjs.map +7 -0
  50. package/dist/js/chunks/chunk-NQLC3YMW.mjs +1 -0
  51. package/dist/js/chunks/chunk-O5XPWXIQ.mjs +406 -0
  52. package/dist/js/chunks/chunk-O5XPWXIQ.mjs.map +7 -0
  53. package/dist/js/chunks/chunk-P3G3QHII.mjs +166 -0
  54. package/dist/js/chunks/chunk-P3G3QHII.mjs.map +7 -0
  55. package/dist/js/chunks/{chunk-VAS6JQ6P.mjs → chunk-PIJ2TAR3.mjs} +3 -3
  56. package/dist/js/chunks/{chunk-74N6U5JJ.mjs → chunk-PLYXLSH3.mjs} +38 -37
  57. package/dist/js/chunks/chunk-PLYXLSH3.mjs.map +7 -0
  58. package/dist/js/chunks/{chunk-PIIAEYAJ.mjs → chunk-QDAL4IYN.mjs} +2 -2
  59. package/dist/js/chunks/chunk-QKWPQK5N.mjs +179 -0
  60. package/dist/js/chunks/chunk-QKWPQK5N.mjs.map +7 -0
  61. package/dist/js/chunks/{chunk-FRB7TOCS.mjs → chunk-QV2JAWIZ.mjs} +2 -2
  62. package/dist/js/chunks/{chunk-N3UHGN3N.mjs → chunk-QVVEWBOF.mjs} +3 -3
  63. package/dist/js/chunks/chunk-RHRQKTTX.mjs +139 -0
  64. package/dist/js/chunks/chunk-RHRQKTTX.mjs.map +7 -0
  65. package/dist/js/chunks/chunk-SPETGK25.mjs +59 -0
  66. package/dist/js/chunks/chunk-SPETGK25.mjs.map +7 -0
  67. package/dist/js/chunks/{chunk-TK6PX2GC.mjs → chunk-U2OTHOTI.mjs} +131 -19
  68. package/dist/js/chunks/chunk-U2OTHOTI.mjs.map +7 -0
  69. package/dist/js/chunks/{chunk-TYM6U5DY.mjs → chunk-UAEAQBRC.mjs} +2 -2
  70. package/dist/js/chunks/{chunk-7UXHSYIA.mjs → chunk-UBLRRJ7N.mjs} +3 -3
  71. package/dist/js/chunks/{chunk-EP3CVKB5.mjs → chunk-UEZUJQ66.mjs} +8 -5
  72. package/dist/js/chunks/chunk-UEZUJQ66.mjs.map +7 -0
  73. package/dist/js/chunks/{chunk-JNPIWFJT.mjs → chunk-UNEMYWEW.mjs} +3 -3
  74. package/dist/js/chunks/chunk-VTLBW7QS.mjs +124 -0
  75. package/dist/js/chunks/chunk-VTLBW7QS.mjs.map +7 -0
  76. package/dist/js/chunks/{chunk-JKNPQQWY.mjs → chunk-WJXDBPXQ.mjs} +28 -12
  77. package/dist/js/chunks/chunk-WJXDBPXQ.mjs.map +7 -0
  78. package/dist/js/chunks/{chunk-CDW6WIRT.mjs → chunk-XGHORT7J.mjs} +18 -11
  79. package/dist/js/chunks/chunk-XGHORT7J.mjs.map +7 -0
  80. package/dist/js/chunks/{chunk-7GKXUG4B.mjs → chunk-XH6BEEMY.mjs} +78 -25
  81. package/dist/js/chunks/chunk-XH6BEEMY.mjs.map +7 -0
  82. package/dist/js/chunks/{chunk-XO5WX3TK.mjs → chunk-YDCS5S3J.mjs} +2 -2
  83. package/dist/js/expressive.cjs +2540 -233
  84. package/dist/js/expressive.cjs.map +4 -4
  85. package/dist/js/expressive.js +2540 -233
  86. package/dist/js/expressive.js.map +4 -4
  87. package/dist/js/expressive.min.js +10 -10
  88. package/dist/js/expressive.min.js.map +4 -4
  89. package/dist/js/expressive.mjs +86 -38
  90. package/dist/js/expressive.mjs.map +1 -1
  91. package/dist/js/internal/behaviors/bottomSheets.mjs +3 -3
  92. package/dist/js/internal/behaviors/dialogs.mjs +2 -2
  93. package/dist/js/internal/behaviors/forms.mjs +2 -2
  94. package/dist/js/internal/behaviors/sheetDrag.mjs +2 -2
  95. package/dist/js/internal/behaviors/sideSheets.mjs +3 -3
  96. package/dist/js/internal/components/appBar.mjs +2 -2
  97. package/dist/js/internal/components/autocomplete.mjs +4 -4
  98. package/dist/js/internal/components/barChart.mjs +10 -0
  99. package/dist/js/internal/components/barChart.mjs.map +7 -0
  100. package/dist/js/internal/components/buttonGroup.mjs +2 -2
  101. package/dist/js/internal/components/buttons.mjs +3 -3
  102. package/dist/js/internal/components/cards.mjs +3 -3
  103. package/dist/js/internal/components/carousel.mjs +3 -3
  104. package/dist/js/internal/components/characterCounter.mjs +2 -2
  105. package/dist/js/internal/components/chips.mjs +5 -5
  106. package/dist/js/internal/components/columnChart.mjs +9 -0
  107. package/dist/js/internal/components/columnChart.mjs.map +7 -0
  108. package/dist/js/internal/components/commandPalette.mjs +9 -0
  109. package/dist/js/internal/components/commandPalette.mjs.map +7 -0
  110. package/dist/js/internal/components/datepicker.mjs +6 -6
  111. package/dist/js/internal/components/expandingCard.mjs +3 -3
  112. package/dist/js/internal/components/heatmapChart.mjs +9 -0
  113. package/dist/js/internal/components/heatmapChart.mjs.map +7 -0
  114. package/dist/js/internal/components/index.mjs +79 -31
  115. package/dist/js/internal/components/lightbox.mjs +3 -3
  116. package/dist/js/internal/components/lineChart.mjs +12 -0
  117. package/dist/js/internal/components/lineChart.mjs.map +7 -0
  118. package/dist/js/internal/components/menu.mjs +3 -3
  119. package/dist/js/internal/components/messageScroller.mjs +9 -0
  120. package/dist/js/internal/components/messageScroller.mjs.map +7 -0
  121. package/dist/js/internal/components/mixedChart.mjs +10 -0
  122. package/dist/js/internal/components/mixedChart.mjs.map +7 -0
  123. package/dist/js/internal/components/navigationRail.mjs +2 -2
  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 +37 -25
  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 +2 -2
  136. package/dist/js/internal/components/select.mjs +4 -4
  137. package/dist/js/internal/components/slider.mjs +3 -3
  138. package/dist/js/internal/components/snackbar.mjs +2 -2
  139. package/dist/js/internal/components/tabs.mjs +4 -4
  140. package/dist/js/internal/components/timepicker.mjs +4 -4
  141. package/dist/js/internal/components/tooltip.mjs +3 -3
  142. package/dist/js/internal/core/component.mjs +1 -1
  143. package/dist/js/internal/core/utils.mjs +1 -1
  144. package/dist/js/internal/plugins/dockedDisplayPlugin.mjs +2 -2
  145. package/dist/js/modular.mjs +86 -38
  146. package/dist/types/behaviors/forms.d.ts +22 -0
  147. package/dist/types/components/appBar.d.ts +1 -1
  148. package/dist/types/components/barChart.d.ts +24 -0
  149. package/dist/types/components/columnChart.d.ts +21 -0
  150. package/dist/types/components/commandPalette.d.ts +96 -0
  151. package/dist/types/components/datepicker.d.ts +5 -2
  152. package/dist/types/components/heatmapChart.d.ts +49 -0
  153. package/dist/types/components/index.d.ts +12 -0
  154. package/dist/types/components/lineChart.d.ts +134 -0
  155. package/dist/types/components/menu.d.ts +32 -0
  156. package/dist/types/components/messageScroller.d.ts +111 -0
  157. package/dist/types/components/mixedChart.d.ts +25 -0
  158. package/dist/types/components/pieChart.d.ts +40 -0
  159. package/dist/types/components/questionnaire.d.ts +96 -0
  160. package/dist/types/components/radarChart.d.ts +39 -0
  161. package/dist/types/components/radialChart.d.ts +45 -0
  162. package/dist/types/components/registry.d.ts +44 -0
  163. package/dist/types/components/richTextEditor.d.ts +71 -0
  164. package/dist/types/components/slider.d.ts +1 -0
  165. package/dist/types/components/snackbar.d.ts +6 -0
  166. package/dist/types/components/timepicker.d.ts +4 -1
  167. package/dist/types/components/tooltip.d.ts +2 -1
  168. package/dist/types/modular.d.ts +10 -1
  169. package/package.json +4 -1
  170. package/src/sass/README.md +3 -6
  171. package/src/sass/abstracts/_index.scss +1 -1
  172. package/src/sass/abstracts/_mixins.scss +226 -0
  173. package/src/sass/abstracts/_variables.scss +14 -0
  174. package/src/sass/base/_typography.scss +45 -0
  175. package/src/sass/components/_accordion.scss +161 -0
  176. package/src/sass/components/_aura.scss +119 -0
  177. package/src/sass/components/_avatar.scss +86 -0
  178. package/src/sass/components/_bar-chart.scss +285 -0
  179. package/src/sass/components/_bottom-sheet.scss +1 -0
  180. package/src/sass/components/_button-groups.scss +13 -3
  181. package/src/sass/components/_cards.scss +16 -13
  182. package/src/sass/components/_carousel.scss +9 -7
  183. package/src/sass/components/_column-chart.scss +134 -0
  184. package/src/sass/components/_command-palette.scss +140 -0
  185. package/src/sass/components/_countdown.scss +89 -0
  186. package/src/sass/components/_data-table.scss +188 -0
  187. package/src/sass/components/_dialog.scss +1 -0
  188. package/src/sass/components/_empty-state.scss +78 -0
  189. package/src/sass/components/_expanding-card.scss +3 -0
  190. package/src/sass/components/_heatmap-chart.scss +156 -0
  191. package/src/sass/components/_index.scss +27 -0
  192. package/src/sass/components/_kpi.scss +162 -0
  193. package/src/sass/components/_line-chart.scss +102 -0
  194. package/src/sass/components/_marquee.scss +111 -0
  195. package/src/sass/components/_menu.scss +10 -0
  196. package/src/sass/components/_message-scroller.scss +66 -0
  197. package/src/sass/components/_message.scss +202 -0
  198. package/src/sass/components/_mixed-chart.scss +157 -0
  199. package/src/sass/components/_navbar.scss +11 -6
  200. package/src/sass/components/_navigation-bar.scss +1 -0
  201. package/src/sass/components/_navigation-rail.scss +9 -0
  202. package/src/sass/components/_page-footer.scss +0 -11
  203. package/src/sass/components/_pie-chart.scss +203 -0
  204. package/src/sass/components/_popover.scss +112 -0
  205. package/src/sass/components/_progress.scss +25 -6
  206. package/src/sass/components/_questionnaire.scss +144 -0
  207. package/src/sass/components/_radar-chart.scss +205 -0
  208. package/src/sass/components/_radial-chart.scss +174 -0
  209. package/src/sass/components/_rich-text-editor.scss +99 -0
  210. package/src/sass/components/_search.scss +1 -0
  211. package/src/sass/components/_side-sheet.scss +1 -0
  212. package/src/sass/components/_skeleton.scss +81 -0
  213. package/src/sass/components/_snackbar.scss +2 -1
  214. package/src/sass/components/_stat.scss +86 -0
  215. package/src/sass/components/_stepper.scss +190 -0
  216. package/src/sass/components/_timeline.scss +114 -0
  217. package/src/sass/components/_timepicker.scss +2 -2
  218. package/src/sass/components/_toolbar.scss +2 -1
  219. package/src/sass/components/_tooltip.scss +2 -0
  220. package/src/sass/components/_tree.scss +139 -0
  221. package/src/sass/components/forms/_checkboxes.scss +2 -2
  222. package/src/sass/components/forms/_drop-zone.scss +128 -0
  223. package/src/sass/components/forms/_index.scss +2 -0
  224. package/src/sass/components/forms/_input-fields.scss +166 -15
  225. package/src/sass/components/forms/_radio-buttons.scss +2 -2
  226. package/src/sass/components/forms/_rating.scss +165 -0
  227. package/src/sass/components/forms/_slider.scss +51 -29
  228. package/src/sass/components/forms/_switches.scss +3 -3
  229. package/src/sass/tokens/_reference.scss +3 -15
  230. package/src/sass/utilities/_helpers.scss +14 -0
  231. package/src/sass/utilities/_index.scss +2 -0
  232. package/src/sass/utilities/_scroll-area.scss +35 -0
  233. package/src/sass/utilities/_shapes.scss +164 -0
  234. package/src/sass/utilities/_spacing.scss +29 -23
  235. package/src/sass/utilities/_visibility.scss +3 -2
  236. package/dist/js/chunks/chunk-74N6U5JJ.mjs.map +0 -7
  237. package/dist/js/chunks/chunk-7GKXUG4B.mjs.map +0 -7
  238. package/dist/js/chunks/chunk-AYYYWUJ4.mjs.map +0 -7
  239. package/dist/js/chunks/chunk-CDW6WIRT.mjs.map +0 -7
  240. package/dist/js/chunks/chunk-D4UZ4HFN.mjs.map +0 -7
  241. package/dist/js/chunks/chunk-EP3CVKB5.mjs.map +0 -7
  242. package/dist/js/chunks/chunk-GY2Z5CJ2.mjs.map +0 -7
  243. package/dist/js/chunks/chunk-I5KR22BY.mjs.map +0 -7
  244. package/dist/js/chunks/chunk-JKNPQQWY.mjs.map +0 -7
  245. package/dist/js/chunks/chunk-JODJAGFS.mjs.map +0 -7
  246. package/dist/js/chunks/chunk-JR24UB4X.mjs +0 -100
  247. package/dist/js/chunks/chunk-JR24UB4X.mjs.map +0 -7
  248. package/dist/js/chunks/chunk-LZVBJ33S.mjs.map +0 -7
  249. package/dist/js/chunks/chunk-PMBPAFAS.mjs +0 -7
  250. package/dist/js/chunks/chunk-PMBPAFAS.mjs.map +0 -7
  251. package/dist/js/chunks/chunk-TK6PX2GC.mjs.map +0 -7
  252. package/dist/js/chunks/chunk-WWPAPHMA.mjs +0 -1
  253. /package/dist/js/chunks/{chunk-IMUPRRI6.mjs.map → chunk-3VOK6J7U.mjs.map} +0 -0
  254. /package/dist/js/chunks/{chunk-A3BJA7V4.mjs.map → chunk-6WLSDZ4O.mjs.map} +0 -0
  255. /package/dist/js/chunks/{chunk-KR44BSYQ.mjs.map → chunk-DLWYKFEI.mjs.map} +0 -0
  256. /package/dist/js/chunks/{chunk-SLFNPY5M.mjs.map → chunk-EC63CHXU.mjs.map} +0 -0
  257. /package/dist/js/chunks/{chunk-WWPAPHMA.mjs.map → chunk-NQLC3YMW.mjs.map} +0 -0
  258. /package/dist/js/chunks/{chunk-VAS6JQ6P.mjs.map → chunk-PIJ2TAR3.mjs.map} +0 -0
  259. /package/dist/js/chunks/{chunk-PIIAEYAJ.mjs.map → chunk-QDAL4IYN.mjs.map} +0 -0
  260. /package/dist/js/chunks/{chunk-FRB7TOCS.mjs.map → chunk-QV2JAWIZ.mjs.map} +0 -0
  261. /package/dist/js/chunks/{chunk-N3UHGN3N.mjs.map → chunk-QVVEWBOF.mjs.map} +0 -0
  262. /package/dist/js/chunks/{chunk-TYM6U5DY.mjs.map → chunk-UAEAQBRC.mjs.map} +0 -0
  263. /package/dist/js/chunks/{chunk-7UXHSYIA.mjs.map → chunk-UBLRRJ7N.mjs.map} +0 -0
  264. /package/dist/js/chunks/{chunk-JNPIWFJT.mjs.map → chunk-UNEMYWEW.mjs.map} +0 -0
  265. /package/dist/js/chunks/{chunk-XO5WX3TK.mjs.map → chunk-YDCS5S3J.mjs.map} +0 -0
@@ -0,0 +1,162 @@
1
+ @use "../abstracts" as *;
2
+
3
+ // KPI. One key figure in a card: an <article class="kpi"> holding a <dl>
4
+ // with a <dt> label, a <dd class="kpi-value"> and an optional
5
+ // <dd class="kpi-trend"> chip. The article is a card, so filled and
6
+ // outlined work as they do there.
7
+ //
8
+ // Optional parts, in source order after the <dl>:
9
+ // .kpi-icon a tonal icon box, written inside the <dt>
10
+ // .kpi-actions a button or menu, placed at the end of the label row
11
+ // a chart a sparkline .line-chart or .column-chart figure
12
+ // .progress a <progress> bar toward a goal
13
+ // <p> supporting text
14
+ // .kpi-footer details or links under a divider
15
+ //
16
+ // .kpi-trend takes .up or .down for the arrow and .negative when the change
17
+ // is bad news; .negative also turns a line, column, bar or mixed chart's
18
+ // first series to the error color. The arrow is decoration: say the
19
+ // direction in the text, as in "+12%".
20
+ //
21
+ // Tokens:
22
+ // --md-comp-kpi-icon-container-color primary-container
23
+ // --md-comp-kpi-icon-color on-primary-container
24
+ // --md-comp-kpi-trend-container-color secondary-container
25
+ // --md-comp-kpi-trend-color on-secondary-container
26
+
27
+ $_trend-charts: "line-chart", "column-chart", "bar-chart", "mixed-chart";
28
+
29
+ .kpi {
30
+ --md-comp-kpi-icon-container-color: var(--md-sys-color-primary-container);
31
+ --md-comp-kpi-icon-color: var(--md-sys-color-on-primary-container);
32
+ --md-comp-kpi-trend-container-color: var(--md-sys-color-secondary-container);
33
+ --md-comp-kpi-trend-color: var(--md-sys-color-on-secondary-container);
34
+
35
+ display: flex;
36
+ flex-direction: column;
37
+ gap: 12px;
38
+ padding: var(--md-comp-card-content-padding, 16px);
39
+
40
+ > * {
41
+ min-width: 0;
42
+ margin: 0;
43
+ }
44
+
45
+ > dl {
46
+ display: flex;
47
+ flex-wrap: wrap;
48
+ align-items: center;
49
+ gap: 8px;
50
+ }
51
+
52
+ &:has(> .kpi-actions) > dl {
53
+ padding-inline-end: 40px;
54
+ }
55
+
56
+ // The card is the containing block, so the button sits in its corner
57
+ // without making the label row taller.
58
+ > .kpi-actions {
59
+ position: absolute;
60
+ inset-block-start: 8px;
61
+ inset-inline-end: 8px;
62
+ }
63
+
64
+ dt {
65
+ display: flex;
66
+ flex-basis: 100%;
67
+ align-items: center;
68
+ gap: 12px;
69
+ color: var(--md-sys-color-on-surface-variant);
70
+ @include typescale("title-small");
71
+ }
72
+
73
+ dd {
74
+ margin: 0;
75
+ }
76
+
77
+ .kpi-icon {
78
+ display: grid;
79
+ flex: none;
80
+ place-items: center;
81
+ width: 40px;
82
+ height: 40px;
83
+ border-radius: 12px;
84
+ background-color: var(--md-comp-kpi-icon-container-color);
85
+ color: var(--md-comp-kpi-icon-color);
86
+ font-size: 24px;
87
+ }
88
+
89
+ .kpi-value {
90
+ min-width: 0;
91
+ overflow-wrap: anywhere;
92
+ color: var(--md-sys-color-on-surface);
93
+ font-variant-numeric: tabular-nums;
94
+ @include typescale("headline-large");
95
+ }
96
+
97
+ .kpi-trend {
98
+ display: inline-flex;
99
+ align-items: center;
100
+ gap: 2px;
101
+ padding: 2px 8px;
102
+ border-radius: 8px;
103
+ background-color: var(--md-comp-kpi-trend-container-color);
104
+ color: var(--md-comp-kpi-trend-color);
105
+ font-variant-numeric: tabular-nums;
106
+ @include typescale("label-large");
107
+
108
+ &:is(.up, .down) {
109
+ padding-inline-start: 4px;
110
+ }
111
+
112
+ &:is(.up, .down)::before {
113
+ content: "";
114
+ flex: none;
115
+ width: 18px;
116
+ height: 18px;
117
+ background-color: currentColor;
118
+ mask: $trend-arrow center / 18px no-repeat;
119
+ }
120
+
121
+ &.down::before {
122
+ transform: rotate(180deg);
123
+ }
124
+
125
+ &.negative {
126
+ --md-comp-kpi-trend-container-color: var(--md-sys-color-error-container);
127
+ --md-comp-kpi-trend-color: var(--md-sys-color-on-error-container);
128
+ }
129
+ }
130
+
131
+ > p {
132
+ padding: 0;
133
+ color: var(--md-sys-color-on-surface-variant);
134
+ @include typescale("body-medium");
135
+ }
136
+
137
+ > .kpi-footer {
138
+ // Auto top margin keeps the footer at the bottom of a stretched card.
139
+ margin: auto calc(-1 * var(--md-comp-card-content-padding, 16px)) calc(-1 * var(--md-comp-card-content-padding, 16px));
140
+ padding: 12px var(--md-comp-card-content-padding, 16px);
141
+ border-top: 1px solid var(--md-sys-color-outline-variant);
142
+ color: var(--md-sys-color-on-surface-variant);
143
+ @include typescale("body-medium");
144
+ }
145
+ }
146
+
147
+ @each $chart in $_trend-charts {
148
+ .kpi:has(.kpi-trend.negative) > .#{$chart} {
149
+ --md-comp-#{$chart}-color-1: var(--md-sys-color-error);
150
+ }
151
+ }
152
+
153
+ @media (forced-colors: active) {
154
+ .kpi-trend {
155
+ outline: 1px solid CanvasText;
156
+ }
157
+
158
+ .kpi-trend::before {
159
+ forced-color-adjust: none;
160
+ background-color: CanvasText;
161
+ }
162
+ }
@@ -0,0 +1,102 @@
1
+ @use "../abstracts" as *;
2
+
3
+ // Line chart. A <figure class="line-chart"> holds a <figcaption> and a
4
+ // <table> of data: the first column labels the x axis, each further column
5
+ // is a series named by its header cell. Without JavaScript the table shows.
6
+ // LineChart draws an SVG from the table and hides the table visually, so a
7
+ // screen reader still reads the data as a table. The plot, tooltip, labels
8
+ // and legend are shared with the column chart through chart().
9
+ //
10
+ // The SVG stretches to the plot (preserveAspectRatio="none") and strokes
11
+ // stay a constant width, so resizing needs no script. Points, the cursor
12
+ // and the tooltip are HTML positioned in percentages for the same reason.
13
+ //
14
+ // Modifiers: .area fills under each line, .stacked stacks each series on
15
+ // the ones before it and fills between them, .fade fades the line ends,
16
+ // .sparkline is a small chart with no axis, grid, legend or tooltip.
17
+ // A series header cell's classes reach its line: <th class="dashed">.
18
+ //
19
+ // Tokens:
20
+ // --md-comp-line-chart-height 240px (sparkline 48px)
21
+ // --md-comp-line-chart-line-width 3px (sparkline 2px)
22
+ // --md-comp-line-chart-grid-color outline-variant
23
+ // --md-comp-line-chart-color-1..4 primary, tertiary, secondary,
24
+ // on-surface-variant
25
+
26
+ @include chart("line-chart");
27
+
28
+ .line-chart {
29
+ --md-comp-line-chart-line-width: 3px;
30
+
31
+ &.sparkline {
32
+ --md-comp-line-chart-line-width: 2px;
33
+ }
34
+ }
35
+
36
+ .line-chart-plot > svg {
37
+ position: absolute;
38
+ inset: 0;
39
+ width: 100%;
40
+ height: 100%;
41
+ overflow: visible;
42
+ }
43
+
44
+ .line-chart-line {
45
+ fill: none;
46
+ stroke: var(--line-chart-color);
47
+ stroke-width: var(--md-comp-line-chart-line-width);
48
+ stroke-linecap: round;
49
+ stroke-linejoin: round;
50
+ vector-effect: non-scaling-stroke;
51
+ }
52
+
53
+ .line-chart-series.dashed .line-chart-line {
54
+ stroke-dasharray: 2 8;
55
+ }
56
+
57
+ .line-chart-area {
58
+ display: none;
59
+
60
+ .line-chart:is(.area, .stacked) & {
61
+ display: inline;
62
+ }
63
+ }
64
+
65
+ .line-chart-series stop {
66
+ stop-color: var(--line-chart-color);
67
+ stop-opacity: 0;
68
+
69
+ &:first-child {
70
+ stop-opacity: 0.24;
71
+ }
72
+ }
73
+
74
+ .line-chart.fade .line-chart-plot > svg {
75
+ mask-image: linear-gradient(to right, transparent, #000 15% 85%, transparent);
76
+ }
77
+
78
+ .line-chart-cursor {
79
+ width: 1px;
80
+ background-color: var(--md-sys-color-outline);
81
+
82
+ > span {
83
+ position: absolute;
84
+ left: 0;
85
+ width: 10px;
86
+ height: 10px;
87
+ border: 2px solid var(--md-sys-color-surface);
88
+ border-radius: 50%;
89
+ background-color: var(--line-chart-color);
90
+ translate: -50% -50%;
91
+ }
92
+ }
93
+
94
+ @media (forced-colors: active) {
95
+ .line-chart-cursor {
96
+ background-color: CanvasText;
97
+ }
98
+
99
+ .line-chart-cursor > span {
100
+ forced-color-adjust: none;
101
+ }
102
+ }
@@ -0,0 +1,111 @@
1
+ @use "../abstracts" as *;
2
+
3
+ // Marquee. A strip of logos, images or text that scrolls without end:
4
+ // <div class="marquee"> holding two identical <ul class="marquee-content">
5
+ // groups. The second is a copy that fills the gap as the first scrolls
6
+ // out. Mark it aria-hidden="true" and give each link or button in it
7
+ // tabindex="-1", so screen readers and the Tab key meet each item once and
8
+ // a click on the copy still works. Each group is at least as wide as the
9
+ // strip and spreads short content out, so one copy is always enough.
10
+ //
11
+ // Both groups move one group's length plus the gap per cycle, then jump
12
+ // back to where they started, which looks the same.
13
+ //
14
+ // Modifiers:
15
+ // .vertical scroll up; the strip is 320px tall unless the page sets a height
16
+ // .reverse scroll toward the inline end, or down
17
+ // .fade fade the items out at both edges
18
+ // .paused stop; toggle it from a pause button
19
+ //
20
+ // Hover or focus inside the strip also pauses it, so a link holds still
21
+ // while it is read or tabbed to. Horizontal strips scroll toward the inline
22
+ // start, so right to left pages scroll right. Reduced motion stops the
23
+ // scroll, drops the copy and lets the strip scroll by hand.
24
+ //
25
+ // Tokens:
26
+ // --md-comp-marquee-duration one cycle 20s
27
+ // --md-comp-marquee-gap space between items and groups 32px
28
+ // --md-comp-marquee-fade-size length of each edge fade (.fade) 48px
29
+
30
+ .marquee {
31
+ --md-comp-marquee-duration: 20s;
32
+ --md-comp-marquee-gap: 32px;
33
+ --md-comp-marquee-fade-size: 48px;
34
+ --_sign: 1;
35
+
36
+ display: flex;
37
+ gap: var(--md-comp-marquee-gap);
38
+ overflow: hidden;
39
+
40
+ &:dir(rtl) {
41
+ --_sign: -1;
42
+ }
43
+
44
+ &.vertical {
45
+ flex-direction: column;
46
+ height: 320px;
47
+ }
48
+
49
+ &.fade {
50
+ --_fade: transparent, #000 var(--md-comp-marquee-fade-size), #000 calc(100% - var(--md-comp-marquee-fade-size)), transparent;
51
+ mask-image: linear-gradient(to right, var(--_fade));
52
+ }
53
+
54
+ &.vertical.fade {
55
+ mask-image: linear-gradient(to bottom, var(--_fade));
56
+ }
57
+ }
58
+
59
+ .marquee-content {
60
+ display: flex;
61
+ flex: none;
62
+ align-items: center;
63
+ justify-content: space-around;
64
+ gap: var(--md-comp-marquee-gap);
65
+ min-width: 100%;
66
+ margin: 0;
67
+ padding: 0;
68
+ list-style: none;
69
+ animation: marquee-x var(--md-comp-marquee-duration) linear infinite;
70
+
71
+ > * {
72
+ flex: none;
73
+ }
74
+
75
+ .vertical > & {
76
+ flex-direction: column;
77
+ min-width: 0;
78
+ min-height: 100%;
79
+ animation-name: marquee-y;
80
+ }
81
+
82
+ .reverse > & {
83
+ animation-direction: reverse;
84
+ }
85
+
86
+ .marquee:is(:hover, :focus-within, .paused) > & {
87
+ animation-play-state: paused;
88
+ }
89
+ }
90
+
91
+ @media (prefers-reduced-motion: reduce) {
92
+ .marquee {
93
+ overflow: auto;
94
+ }
95
+
96
+ .marquee-content {
97
+ animation: none;
98
+
99
+ &[aria-hidden="true"] {
100
+ display: none;
101
+ }
102
+ }
103
+ }
104
+
105
+ @keyframes marquee-x {
106
+ to { translate: calc((100% + var(--md-comp-marquee-gap)) * var(--_sign) * -1) 0; }
107
+ }
108
+
109
+ @keyframes marquee-y {
110
+ to { translate: 0 calc(-100% - var(--md-comp-marquee-gap)); }
111
+ }
@@ -78,6 +78,7 @@ $_menu-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg
78
78
  color: var(--md-comp-menu-item-label-text-color);
79
79
  @include z-depth("2");
80
80
  transition: border-radius 200ms ease;
81
+ @include glass(var(--md-comp-menu-container-color));
81
82
 
82
83
  // The [vibrant] arms are not a second mapping - they are the statement that
83
84
  // a menu on a vibrant surface IS a vibrant menu. Without them the foundation
@@ -360,6 +361,10 @@ $_menu-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg
360
361
  filter: drop-shadow(0 3px 3px rgba(0, 0, 0, 0.14))
361
362
  drop-shadow(0 1px 4px rgba(0, 0, 0, 0.12));
362
363
 
364
+ // The drop-shadow filter is the items' backdrop root, so they could only
365
+ // blur the menu itself. Grouped menus stay solid.
366
+ backdrop-filter: none;
367
+
363
368
  > li:not(.divider, .optgroup, .gap, .label) {
364
369
  padding-inline: var(--md-comp-menu-group-padding);
365
370
  background-color: var(--md-comp-menu-container-color);
@@ -605,6 +610,11 @@ menu[id].grouped
605
610
  .menu-trigger {
606
611
  cursor: pointer;
607
612
 
613
+ // A context menu's trigger is a region of content, not a control.
614
+ &[data-context-menu] {
615
+ cursor: auto;
616
+ }
617
+
608
618
  // The trigger stays in its pressed state for as long as its menu is open.
609
619
  &[aria-expanded="true"] {
610
620
  background-image: linear-gradient(
@@ -0,0 +1,66 @@
1
+ @use "../abstracts" as *;
2
+
3
+ // Message scroller. A chat frame around one scrolling viewport of messages
4
+ // and a scroll-to-latest button. The frame fills its parent, so the parent
5
+ // sets the height. The script owns scroll position; this partial only lays
6
+ // out the parts.
7
+ //
8
+ // The script turns off native scroll anchoring on the viewport and keeps the
9
+ // reader's place itself, so all engines behave the same. It writes
10
+ // --md-comp-message-scroller-spacer (blank space after the last message) so a
11
+ // newly anchored turn can reach the top of the viewport.
12
+ //
13
+ // Tokens:
14
+ // --md-comp-message-scroller-padding 16px (viewport inset)
15
+ // --md-comp-message-scroller-gap 16px (between messages)
16
+
17
+ .message-scroller {
18
+ --md-comp-message-scroller-padding: 16px;
19
+ --md-comp-message-scroller-gap: 16px;
20
+
21
+ position: relative;
22
+ display: flex;
23
+ flex-direction: column;
24
+ min-height: 0;
25
+ height: 100%;
26
+ }
27
+
28
+ .message-scroller-viewport {
29
+ box-sizing: border-box;
30
+ flex: 1;
31
+ min-height: 0;
32
+ overflow-y: auto;
33
+ overflow-anchor: none;
34
+ overscroll-behavior: contain;
35
+ padding: var(--md-comp-message-scroller-padding);
36
+ padding-block-end: calc(var(--md-comp-message-scroller-padding) + var(--md-comp-message-scroller-spacer, 0px));
37
+
38
+ @include focus-visible;
39
+
40
+ > * + * {
41
+ margin-block-start: var(--md-comp-message-scroller-gap);
42
+ }
43
+ }
44
+
45
+ // Centered over the bottom of the viewport. Inert while there is nothing
46
+ // below; it fades out instead of leaving a hidden tab stop.
47
+ .message-scroller-button {
48
+ position: absolute;
49
+ inset-block-end: 16px;
50
+ inset-inline: 0;
51
+ width: fit-content;
52
+ margin-inline: auto;
53
+ @include z-depth("2");
54
+ transition: opacity .15s ease-out, scale .15s ease-out;
55
+
56
+ &[inert] {
57
+ opacity: 0;
58
+ scale: .8;
59
+ }
60
+ }
61
+
62
+ @media (prefers-reduced-motion: reduce) {
63
+ .message-scroller-button {
64
+ transition: none;
65
+ }
66
+ }
@@ -0,0 +1,202 @@
1
+ @use "../abstracts" as *;
2
+
3
+ // Message. One message in a conversation: an optional avatar, header and
4
+ // footer around a single surface. The surface is every other child, normally
5
+ // one .message-bubble; wrap several elements in a <div> to keep them on one
6
+ // surface. `.end` moves the row to the sender's side.
7
+ //
8
+ // The parts are divs, not <header>/<footer>: outside sectioning content those
9
+ // elements become banner and contentinfo landmarks, one per message.
10
+ //
11
+ // The grid puts the avatar in the surface row, so it lines up with the bottom
12
+ // of the bubble and a footer below never pushes it down.
13
+ //
14
+ // Tokens:
15
+ // --md-comp-message-avatar-size 32px
16
+ // --md-comp-message-gap 8px (avatar to surface)
17
+ // --md-comp-message-surface-max-width 80%
18
+ // --md-comp-message-bubble-shape 20px
19
+ // --md-comp-message-bubble-grouped-shape 4px (joined corners in a group)
20
+ // --md-comp-message-bubble-container-color surface-container-high / end: primary-container
21
+ // --md-comp-message-bubble-color on-surface / end: on-primary-container
22
+ // --md-comp-message-group-gap 2px
23
+
24
+ .message {
25
+ --md-comp-message-avatar-size: 32px;
26
+ --md-comp-message-gap: 8px;
27
+ --md-comp-message-surface-max-width: 80%;
28
+ --md-comp-message-bubble-shape: 20px;
29
+ --md-comp-message-bubble-grouped-shape: 4px;
30
+ --md-comp-message-bubble-container-color: var(--md-sys-color-surface-container-high);
31
+ --md-comp-message-bubble-color: var(--md-sys-color-on-surface);
32
+
33
+ display: grid;
34
+ grid-template-columns: auto minmax(0, 1fr);
35
+ grid-template-areas:
36
+ ". header"
37
+ "avatar surface"
38
+ ". footer";
39
+ align-items: end;
40
+ justify-items: start;
41
+ color: var(--md-sys-color-on-surface);
42
+
43
+ > .message-avatar {
44
+ grid-area: avatar;
45
+ margin-inline-end: var(--md-comp-message-gap);
46
+ }
47
+
48
+ > .message-header {
49
+ grid-area: header;
50
+ }
51
+
52
+ > .message-footer {
53
+ grid-area: footer;
54
+ }
55
+
56
+ > :not(.message-avatar, .message-header, .message-footer) {
57
+ grid-area: surface;
58
+ min-width: 0;
59
+ max-width: var(--md-comp-message-surface-max-width);
60
+ }
61
+
62
+ &.end {
63
+ --md-comp-message-bubble-container-color: var(--md-sys-color-primary-container);
64
+ --md-comp-message-bubble-color: var(--md-sys-color-on-primary-container);
65
+
66
+ grid-template-columns: minmax(0, 1fr) auto;
67
+ grid-template-areas:
68
+ "header ."
69
+ "surface avatar"
70
+ "footer .";
71
+ justify-items: end;
72
+
73
+ > .message-avatar {
74
+ margin-inline: var(--md-comp-message-gap) 0;
75
+ }
76
+ }
77
+ }
78
+
79
+ // An <img>, or a box holding initials, an icon or an <img>. An empty one is a
80
+ // spacer that keeps earlier messages in a group in line with the last.
81
+ .message-avatar {
82
+ box-sizing: border-box;
83
+ display: inline-flex;
84
+ align-items: center;
85
+ justify-content: center;
86
+ width: var(--md-comp-message-avatar-size);
87
+ height: var(--md-comp-message-avatar-size);
88
+ border-radius: 50%;
89
+ overflow: hidden;
90
+ object-fit: cover;
91
+ @include typescale("label-medium");
92
+
93
+ &:not(img):not(:empty) {
94
+ background-color: var(--md-sys-color-secondary-container);
95
+ color: var(--md-sys-color-on-secondary-container);
96
+ }
97
+
98
+ > img {
99
+ width: 100%;
100
+ height: 100%;
101
+ object-fit: cover;
102
+ }
103
+
104
+ > #{$icon} {
105
+ font-size: 20px;
106
+ }
107
+ }
108
+
109
+ .message-header,
110
+ .message-footer {
111
+ display: flex;
112
+ flex-wrap: wrap;
113
+ align-items: center;
114
+ gap: 4px;
115
+ padding-inline: 12px;
116
+ color: var(--md-sys-color-on-surface-variant);
117
+ @include typescale("label-medium");
118
+ }
119
+
120
+ .message-header {
121
+ margin-block-end: 4px;
122
+ }
123
+
124
+ .message-footer {
125
+ margin-block-start: 4px;
126
+
127
+ // Icon buttons carry their own inset; drop the text inset so the first
128
+ // icon sits under the bubble edge rather than past it.
129
+ &:has(> .icon-button:first-child) {
130
+ padding-inline: 0;
131
+ }
132
+ }
133
+
134
+ .message-bubble {
135
+ box-sizing: border-box;
136
+ margin: 0;
137
+ padding: 10px 16px;
138
+ border-radius: var(--md-comp-message-bubble-shape);
139
+ background-color: var(--md-comp-message-bubble-container-color);
140
+ color: var(--md-comp-message-bubble-color);
141
+ overflow-wrap: anywhere;
142
+ @include typescale("body-large");
143
+
144
+ > * {
145
+ margin-block: 0;
146
+ }
147
+
148
+ > * + * {
149
+ margin-block-start: 8px;
150
+ }
151
+
152
+ // Attachments and rich content: no fill, an outline-variant border.
153
+ &.outlined {
154
+ --md-comp-message-bubble-container-color: transparent;
155
+ --md-comp-message-bubble-color: var(--md-sys-color-on-surface);
156
+
157
+ border: 1px solid var(--md-sys-color-outline-variant);
158
+ }
159
+
160
+ // A bubble holding only an image or video frames it with a thin inset.
161
+ &:has(> :is(img, video, picture):only-child) {
162
+ padding: 4px;
163
+ }
164
+
165
+ > :is(img, video),
166
+ > picture > img {
167
+ display: block;
168
+ max-width: 100%;
169
+ height: auto;
170
+ border-radius: calc(var(--md-comp-message-bubble-shape) - 4px);
171
+ }
172
+ }
173
+
174
+ // Consecutive messages from one sender. The bubbles join on the sender's
175
+ // side: inner corners shrink to the grouped shape.
176
+ .message-group {
177
+ --md-comp-message-group-gap: 2px;
178
+
179
+ display: flex;
180
+ flex-direction: column;
181
+ gap: var(--md-comp-message-group-gap);
182
+
183
+ > .message:not(.end) {
184
+ &:not(:first-child) .message-bubble {
185
+ border-start-start-radius: var(--md-comp-message-bubble-grouped-shape);
186
+ }
187
+
188
+ &:not(:last-child) .message-bubble {
189
+ border-end-start-radius: var(--md-comp-message-bubble-grouped-shape);
190
+ }
191
+ }
192
+
193
+ > .message.end {
194
+ &:not(:first-child) .message-bubble {
195
+ border-start-end-radius: var(--md-comp-message-bubble-grouped-shape);
196
+ }
197
+
198
+ &:not(:last-child) .message-bubble {
199
+ border-end-end-radius: var(--md-comp-message-bubble-grouped-shape);
200
+ }
201
+ }
202
+ }