@kubex/zinc 1.1.184 → 2.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 (362) hide show
  1. package/.browserslistrc +2 -0
  2. package/.github/workflows/js_build_and_deploy.yaml +54 -1
  3. package/.github/workflows/test.yaml +27 -0
  4. package/dist/chunks/zn.UWJLIXDT.js +1 -0
  5. package/dist/custom-elements.json +10344 -2583
  6. package/dist/vscode.html-custom-data.json +1102 -125
  7. package/dist/web-types.json +2217 -224
  8. package/dist/zn.d.ts +2306 -417
  9. package/dist/zn.min.css +1 -1
  10. package/dist/zn.min.js +2313 -1635
  11. package/docs/_includes/default.njk +4 -1
  12. package/docs/assets/scripts/docs.js +22 -6
  13. package/docs/assets/styles/docs.css +9 -2
  14. package/docs/data/report-table-day-compare.json +380 -0
  15. package/docs/data/report-table.json +314 -0
  16. package/docs/pages/components/avatar-group.md +57 -0
  17. package/docs/pages/components/badge.md +67 -0
  18. package/docs/pages/components/button.md +41 -1
  19. package/docs/pages/components/chat-message.md +16 -0
  20. package/docs/pages/components/checkbox.md +1 -1
  21. package/docs/pages/components/chip.md +25 -13
  22. package/docs/pages/components/color-picker.md +37 -0
  23. package/docs/pages/components/copy-button.md +2 -2
  24. package/docs/pages/components/data-table-filter.md +33 -50
  25. package/docs/pages/components/data-table-search.md +4 -4
  26. package/docs/pages/components/data-table.md +27 -3
  27. package/docs/pages/components/date-range.md +116 -0
  28. package/docs/pages/components/dialog.md +29 -37
  29. package/docs/pages/components/diff-row.md +28 -0
  30. package/docs/pages/components/diff.md +46 -0
  31. package/docs/pages/components/editor.md +55 -0
  32. package/docs/pages/components/filter-wrapper.md +20 -0
  33. package/docs/pages/components/icon.md +46 -1
  34. package/docs/pages/components/input.md +30 -11
  35. package/docs/pages/components/item.md +35 -0
  36. package/docs/pages/components/key-value.md +25 -0
  37. package/docs/pages/components/menu.md +74 -7
  38. package/docs/pages/components/nav-item.md +15 -0
  39. package/docs/pages/components/nav-list.md +132 -0
  40. package/docs/pages/components/navbar.md +100 -1
  41. package/docs/pages/components/page.md +242 -74
  42. package/docs/pages/components/priority-list.md +43 -5
  43. package/docs/pages/components/query-builder.md +23 -0
  44. package/docs/pages/components/radio-group.md +33 -1
  45. package/docs/pages/components/radio.md +1 -1
  46. package/docs/pages/components/report-table.md +202 -0
  47. package/docs/pages/components/stat.md +30 -0
  48. package/docs/pages/components/tile.md +11 -0
  49. package/docs/pages/components/tooltip.md +1 -1
  50. package/docs/pages/components/translation-grid.md +86 -0
  51. package/docs/pages/components/vertical-stepper.md +108 -64
  52. package/package.json +2 -1
  53. package/scss/_global-spacing.scss +2 -2
  54. package/scss/_root.scss +11 -171
  55. package/scss/boot.scss +14 -0
  56. package/scss/mixins/_helper-mixins.scss +24 -2
  57. package/scss/mixins/_motion-mixins.scss +126 -0
  58. package/scss/mixins/_spacing-mixins.scss +4 -3
  59. package/scss/mixins/_tab-indicator-mixins.scss +12 -0
  60. package/scss/mixins/_typography-mixins.scss +1 -1
  61. package/scss/mixins/index.scss +14 -0
  62. package/scss/shared/_base.scss +32 -1
  63. package/scss/shared/_button-mixin.scss +7 -5
  64. package/scss/shared/_table.scss +35 -4
  65. package/scss/shared/nav.scss +4 -0
  66. package/scss/shared/shimmer.scss +1 -1
  67. package/scss/table-controls.scss +206 -0
  68. package/scss/themes/_dark.scss +1 -3
  69. package/scss/themes/_index.scss +1 -1
  70. package/scss/themes/_light.scss +46 -6
  71. package/scss/themes/_modes.scss +11 -11
  72. package/scss/themes/_openbyte.scss +944 -0
  73. package/scss/themes/_typography.scss +4 -2
  74. package/scss/variables/index.scss +0 -9
  75. package/src/components/alert/alert.component.ts +14 -4
  76. package/src/components/alert/alert.scss +55 -69
  77. package/src/components/alert/alert.test.ts +8 -0
  78. package/src/components/animated-button/animated-button.component.ts +3 -2
  79. package/src/components/animated-button/animated-button.scss +6 -23
  80. package/src/components/animated-button/animated-button.test.ts +4 -3
  81. package/src/components/avatar-group/avatar-group.component.ts +84 -0
  82. package/src/components/avatar-group/avatar-group.scss +54 -0
  83. package/src/components/avatar-group/avatar-group.test.ts +59 -0
  84. package/src/components/avatar-group/index.ts +12 -0
  85. package/src/components/badge/badge.component.ts +49 -0
  86. package/src/components/badge/badge.scss +80 -0
  87. package/src/components/badge/badge.test.ts +34 -0
  88. package/src/components/badge/index.ts +12 -0
  89. package/src/components/bulk-actions/bulk-actions.component.ts +14 -2
  90. package/src/components/button/button.component.ts +242 -11
  91. package/src/components/button/button.scss +133 -25
  92. package/src/components/button/button.test.ts +122 -0
  93. package/src/components/button-menu/button-menu.component.ts +32 -11
  94. package/src/components/button-menu/button-menu.scss +5 -1
  95. package/src/components/channel-tile/channel-tile.component.ts +34 -27
  96. package/src/components/channel-tile/channel-tile.scss +76 -43
  97. package/src/components/chart/builders.test.ts +46 -0
  98. package/src/components/chart/builders.ts +27 -3
  99. package/src/components/chart/chart-live.test.ts +4 -6
  100. package/src/components/chart/chart.component.ts +125 -5
  101. package/src/components/chart/chart.scss +121 -0
  102. package/src/components/chart/chart.test.ts +81 -0
  103. package/src/components/chat-message/chat-message.component.ts +21 -1
  104. package/src/components/chat-message/chat-message.scss +13 -2
  105. package/src/components/chat-message/chat-message.test.ts +9 -0
  106. package/src/components/checkbox/checkbox.component.ts +61 -27
  107. package/src/components/checkbox/checkbox.scss +58 -25
  108. package/src/components/checkbox-group/checkbox-group.component.ts +7 -1
  109. package/src/components/chip/chip.component.ts +11 -1
  110. package/src/components/chip/chip.scss +91 -26
  111. package/src/components/chip/chip.test.ts +17 -0
  112. package/src/components/collapsible/collapsible.component.ts +17 -3
  113. package/src/components/collapsible/collapsible.scss +19 -10
  114. package/src/components/color-picker/color-picker.component.ts +277 -0
  115. package/src/components/color-picker/color-picker.scss +141 -0
  116. package/src/components/color-picker/color-picker.test.ts +57 -0
  117. package/src/components/color-picker/index.ts +12 -0
  118. package/src/components/cols/cols.component.ts +17 -3
  119. package/src/components/cols/cols.scss +24 -13
  120. package/src/components/cols/cols.test.ts +33 -0
  121. package/src/components/confirm/confirm.component.ts +20 -6
  122. package/src/components/confirm/confirm.test.ts +52 -0
  123. package/src/components/content-block/content-block.component.ts +38 -9
  124. package/src/components/content-block/content-block.scss +11 -5
  125. package/src/components/content-block/content-block.test.ts +26 -0
  126. package/src/components/copy-button/copy-button.component.ts +2 -2
  127. package/src/components/copy-button/copy-button.scss +17 -4
  128. package/src/components/data-select/data-select.component.ts +3 -1
  129. package/src/components/data-table/data-table.component.ts +364 -142
  130. package/src/components/data-table/data-table.scss +133 -60
  131. package/src/components/data-table/data-table.test.ts +356 -4
  132. package/src/components/data-table-filter/data-table-filter.component.ts +426 -406
  133. package/src/components/data-table-filter/data-table-filter.scss +176 -148
  134. package/src/components/data-table-filter/data-table-filter.test.ts +271 -273
  135. package/src/components/data-table-search/data-table-search.component.ts +4 -2
  136. package/src/components/data-table-search/data-table-search.scss +8 -1
  137. package/src/components/data-table-search/data-table-search.test.ts +29 -0
  138. package/src/components/date-range/date-range-math.test.ts +78 -0
  139. package/src/components/date-range/date-range-math.ts +105 -0
  140. package/src/components/date-range/date-range.component.ts +375 -0
  141. package/src/components/date-range/date-range.scss +272 -0
  142. package/src/components/date-range/date-range.test.ts +247 -0
  143. package/src/components/date-range/index.ts +12 -0
  144. package/src/components/datepicker/datepicker.component.ts +44 -7
  145. package/src/components/datepicker/datepicker.scss +9 -0
  146. package/src/components/datepicker/datepicker.test.ts +2 -2
  147. package/src/components/dialog/dialog.component.ts +38 -19
  148. package/src/components/dialog/dialog.scss +65 -36
  149. package/src/components/dialog/dialog.test.ts +14 -0
  150. package/src/components/diff/diff.component.ts +55 -0
  151. package/src/components/diff/diff.scss +46 -0
  152. package/src/components/diff/diff.test.ts +15 -0
  153. package/src/components/diff/index.ts +12 -0
  154. package/src/components/diff-row/diff-row.component.ts +75 -0
  155. package/src/components/diff-row/diff-row.scss +70 -0
  156. package/src/components/diff-row/diff-row.test.ts +37 -0
  157. package/src/components/diff-row/index.ts +12 -0
  158. package/src/components/dropdown/dropdown.component.ts +12 -10
  159. package/src/components/dropdown/dropdown.scss +2 -0
  160. package/src/components/editor/editor.component.ts +159 -11
  161. package/src/components/editor/editor.scss +250 -1
  162. package/src/components/editor/editor.test.ts +31 -3
  163. package/src/components/editor/modules/ai/panel/ai-panel.scss +0 -1
  164. package/src/components/editor/modules/attachment/attachment.ts +53 -31
  165. package/src/components/editor/modules/context-menu/context-menu.ts +17 -0
  166. package/src/components/editor/modules/dialog/dialog.component.ts +23 -1
  167. package/src/components/editor/modules/dialog/dialog.test.ts +28 -0
  168. package/src/components/editor/modules/emoji/emoji.ts +4 -5
  169. package/src/components/editor/modules/merge-field/merge-field.ts +83 -0
  170. package/src/components/editor/modules/toolbar/toolbar.component.ts +121 -68
  171. package/src/components/editor/modules/toolbar/toolbar.scss +38 -0
  172. package/src/components/editor/modules/toolbar/toolbar.ts +25 -1
  173. package/src/components/empty-state/empty-state.component.ts +6 -1
  174. package/src/components/empty-state/empty-state.scss +21 -4
  175. package/src/components/expanding-action/expanding-action.component.ts +22 -34
  176. package/src/components/expanding-action/expanding-action.scss +3 -45
  177. package/src/components/expanding-action/expanding-action.test.ts +2 -1
  178. package/src/components/file/file.component.ts +30 -2
  179. package/src/components/file/file.scss +6 -0
  180. package/src/components/filter-wrapper/filter-wrapper.component.ts +45 -10
  181. package/src/components/filter-wrapper/filter-wrapper.test.ts +58 -2
  182. package/src/components/flow-builder/flow-builder.component.ts +36 -3
  183. package/src/components/flow-builder/flow-builder.scss +0 -6
  184. package/src/components/flow-builder/modules/flow-canvas/flow-canvas.component.ts +8 -0
  185. package/src/components/flow-builder/modules/flow-canvas/flow-canvas.scss +10 -5
  186. package/src/components/flow-builder/modules/flow-node/flow-node.component.ts +17 -0
  187. package/src/components/flow-builder/modules/flow-node/flow-node.scss +10 -0
  188. package/src/components/form-actions/form-actions.component.ts +48 -2
  189. package/src/components/form-actions/form-actions.scss +1 -1
  190. package/src/components/form-group/form-group.component.ts +10 -3
  191. package/src/components/form-group/form-group.scss +37 -4
  192. package/src/components/form-group/form-group.test.ts +10 -0
  193. package/src/components/header/header.component.ts +11 -4
  194. package/src/components/header/header.scss +47 -5
  195. package/src/components/hover-container/hover-container.component.ts +4 -5
  196. package/src/components/icon/icon.component.ts +95 -9
  197. package/src/components/icon/icon.scss +70 -6
  198. package/src/components/icon/icon.test.ts +55 -0
  199. package/src/components/icon-picker/icon-picker.component.ts +35 -1
  200. package/src/components/inline-edit/inline-edit.component.ts +38 -8
  201. package/src/components/inline-edit/inline-edit.scss +128 -19
  202. package/src/components/input/input.component.ts +173 -297
  203. package/src/components/input/input.scss +65 -43
  204. package/src/components/input/input.test.ts +86 -4
  205. package/src/components/item/item.component.ts +12 -0
  206. package/src/components/item/item.scss +102 -3
  207. package/src/components/item/item.test.ts +23 -0
  208. package/src/components/key/key.component.ts +2 -2
  209. package/src/components/key/key.scss +11 -0
  210. package/src/components/key-value/index.ts +12 -0
  211. package/src/components/key-value/key-value.component.ts +160 -0
  212. package/src/components/key-value/key-value.scss +20 -0
  213. package/src/components/key-value/key-value.test.ts +22 -0
  214. package/src/components/markdown-editor/markdown-editor.component.ts +8 -1
  215. package/src/components/menu/menu.component.ts +21 -2
  216. package/src/components/menu/menu.scss +43 -23
  217. package/src/components/menu/menu.test.ts +33 -0
  218. package/src/components/menu-item/menu-item.component.ts +13 -2
  219. package/src/components/menu-item/menu-item.scss +56 -23
  220. package/src/components/menu-item/menu-item.test.ts +31 -0
  221. package/src/components/menu-item/submenu-controller.ts +25 -15
  222. package/src/components/menu-label/index.ts +12 -0
  223. package/src/components/menu-label/menu-label.component.ts +30 -0
  224. package/src/components/menu-label/menu-label.scss +18 -0
  225. package/src/components/nav-item/index.ts +12 -0
  226. package/src/components/nav-item/nav-item.component.ts +83 -0
  227. package/src/components/nav-item/nav-item.scss +128 -0
  228. package/src/components/nav-list/index.ts +12 -0
  229. package/src/components/nav-list/nav-list.component.ts +313 -0
  230. package/src/components/nav-list/nav-list.scss +87 -0
  231. package/src/components/nav-list/nav-list.test.ts +250 -0
  232. package/src/components/navbar/navbar.component.ts +235 -171
  233. package/src/components/navbar/navbar.scss +333 -169
  234. package/src/components/navbar/navbar.test.ts +63 -143
  235. package/src/components/page/page.component.ts +114 -29
  236. package/src/components/page/page.scss +223 -95
  237. package/src/components/page/page.test.ts +214 -3
  238. package/src/components/page-builder/page-builder.component.ts +51 -5
  239. package/src/components/page-builder/page-builder.scss +6 -1
  240. package/src/components/page-nav/page-nav.component.ts +25 -3
  241. package/src/components/page-nav/page-nav.scss +10 -2
  242. package/src/components/pagination/pagination.scss +1 -1
  243. package/src/components/panel/panel.component.ts +14 -13
  244. package/src/components/panel/panel.scss +14 -10
  245. package/src/components/panel/panel.test.ts +42 -0
  246. package/src/components/popup/popup.component.ts +20 -13
  247. package/src/components/popup/popup.test.ts +21 -1
  248. package/src/components/priority-list/priority-list.component.ts +157 -172
  249. package/src/components/priority-list/priority-list.scss +113 -17
  250. package/src/components/priority-list/priority-list.test.ts +301 -3
  251. package/src/components/progress-bar/progress-bar.component.ts +1 -1
  252. package/src/components/progress-bar/progress-bar.scss +16 -4
  253. package/src/components/progress-tile/progress-tile.scss +1 -1
  254. package/src/components/query-builder/query-builder.component.ts +85 -10
  255. package/src/components/query-builder/query-builder.scss +7 -1
  256. package/src/components/query-builder/query-builder.test.ts +40 -0
  257. package/src/components/radio/radio.component.ts +57 -18
  258. package/src/components/radio/radio.scss +101 -26
  259. package/src/components/radio-group/radio-group.component.ts +45 -7
  260. package/src/components/radio-group/radio-group.scss +17 -0
  261. package/src/components/radio-group/radio-group.test.ts +63 -2
  262. package/src/components/rating/rating.component.ts +23 -0
  263. package/src/components/rating/rating.scss +1 -1
  264. package/src/components/remarkd-editor/remarkd-editor.component.ts +60 -5
  265. package/src/components/remarkd-editor/remarkd-editor.scss +12 -4
  266. package/src/components/report-table/index.ts +12 -0
  267. package/src/components/report-table/report-format.test.ts +86 -0
  268. package/src/components/report-table/report-format.ts +72 -0
  269. package/src/components/report-table/report-math.test.ts +74 -0
  270. package/src/components/report-table/report-math.ts +252 -0
  271. package/src/components/report-table/report-table.component.ts +681 -0
  272. package/src/components/report-table/report-table.scss +328 -0
  273. package/src/components/report-table/report-table.test.ts +702 -0
  274. package/src/components/reveal/reveal.component.ts +15 -1
  275. package/src/components/reveal/reveal.scss +5 -0
  276. package/src/components/schedule-builder/schedule-builder.component.ts +23 -8
  277. package/src/components/scroll-container/scroll-container.component.ts +19 -1
  278. package/src/components/scroll-container/scroll-container.scss +6 -1
  279. package/src/components/select/select.component.ts +52 -36
  280. package/src/components/select/select.scss +42 -25
  281. package/src/components/select/select.test.ts +14 -2
  282. package/src/components/settings-container/settings-container.scss +18 -5
  283. package/src/components/sidebar/sidebar.component.ts +8 -1
  284. package/src/components/sidebar/sidebar.scss +6 -1
  285. package/src/components/skeleton/skeleton.component.ts +3 -3
  286. package/src/components/skeleton/skeleton.scss +6 -6
  287. package/src/components/skeleton/skeleton.test.ts +9 -0
  288. package/src/components/slash-menu/slash-menu.scss +1 -1
  289. package/src/components/slideout/slideout.component.ts +20 -3
  290. package/src/components/slideout/slideout.scss +13 -6
  291. package/src/components/slideout/slideout.test.ts +19 -0
  292. package/src/components/split-button/split-button.component.ts +1 -1
  293. package/src/components/split-pane/split-pane.component.ts +71 -8
  294. package/src/components/split-pane/split-pane.scss +145 -41
  295. package/src/components/split-pane/split-pane.test.ts +23 -3
  296. package/src/components/stat/stat.component.ts +209 -14
  297. package/src/components/stat/stat.scss +305 -5
  298. package/src/components/stat/stat.test.ts +143 -2
  299. package/src/components/status-indicator/status-indicator.scss +22 -21
  300. package/src/components/stepper/stepper.scss +3 -3
  301. package/src/components/tab/tab.component.ts +1 -0
  302. package/src/components/table/table.component.ts +12 -1
  303. package/src/components/table/table.scss +21 -13
  304. package/src/components/table/table.test.ts +17 -0
  305. package/src/components/tabs/tabs.component.ts +150 -37
  306. package/src/components/tabs/tabs.scss +48 -7
  307. package/src/components/tabs/tabs.test.ts +169 -0
  308. package/src/components/textarea/textarea.component.ts +25 -3
  309. package/src/components/textarea/textarea.scss +10 -0
  310. package/src/components/textarea/textarea.test.ts +8 -4
  311. package/src/components/theme-editor/theme-editor.scss +0 -6
  312. package/src/components/tile/tile.component.ts +32 -2
  313. package/src/components/tile/tile.scss +40 -7
  314. package/src/components/tile/tile.test.ts +10 -0
  315. package/src/components/toggle/toggle.component.ts +23 -7
  316. package/src/components/toggle/toggle.scss +36 -29
  317. package/src/components/toggle/toggle.test.ts +17 -0
  318. package/src/components/tooltip/tooltip.component.ts +3 -0
  319. package/src/components/tooltip/tooltip.scss +11 -6
  320. package/src/components/tooltip/tooltip.test.ts +12 -0
  321. package/src/components/translation-field/index.ts +12 -0
  322. package/src/components/translation-field/translation-field.component.ts +55 -0
  323. package/src/components/translation-field/translation-field.scss +101 -0
  324. package/src/components/translation-fields/index.ts +12 -0
  325. package/src/components/translation-fields/translation-fields.component.ts +80 -0
  326. package/src/components/translation-fields/translation-fields.scss +60 -0
  327. package/src/components/translation-grid/index.ts +12 -0
  328. package/src/components/translation-grid/translation-grid.component.ts +157 -0
  329. package/src/components/translation-grid/translation-grid.scss +138 -0
  330. package/src/components/translation-grid/translation-grid.test.ts +28 -0
  331. package/src/components/vertical-stepper/vertical-stepper.component.ts +35 -9
  332. package/src/components/vertical-stepper/vertical-stepper.scss +110 -39
  333. package/src/components/vertical-stepper/vertical-stepper.test.ts +35 -0
  334. package/src/components/well/well.scss +2 -2
  335. package/src/events/events.ts +2 -0
  336. package/src/events/zn-chart-click.ts +13 -0
  337. package/src/events/zn-report-change.ts +7 -0
  338. package/src/form-control.scss +36 -3
  339. package/src/internal/anchored-popover.ts +175 -0
  340. package/src/internal/animate.ts +19 -5
  341. package/src/internal/cosmic-border.ts +15 -0
  342. package/src/internal/form.ts +1 -1
  343. package/src/internal/hover-intent.ts +15 -0
  344. package/src/internal/input-modality.ts +15 -0
  345. package/src/internal/pointer-intent.ts +37 -0
  346. package/src/internal/reorder.ts +625 -0
  347. package/src/internal/scroll.ts +51 -3
  348. package/src/internal/selection-card.ts +1 -1
  349. package/src/internal/tab-indicator.ts +92 -0
  350. package/src/internal/table-sort.ts +25 -0
  351. package/src/internal/table-tabs.ts +108 -0
  352. package/src/internal/test-drag.ts +35 -0
  353. package/src/internal/theme-openbyte.test.ts +126 -0
  354. package/src/internal/theme.ts +4 -4
  355. package/src/internal/zinc-element.ts +2 -2
  356. package/src/selection-card.scss +25 -0
  357. package/src/types/web-test-runner-commands.d.ts +1 -0
  358. package/src/utilities/color.test.ts +43 -0
  359. package/src/utilities/color.ts +189 -0
  360. package/src/zinc.ts +14 -0
  361. package/.github/workflows/eleventy_build.yml +0 -42
  362. package/scss/themes/_aura.scss +0 -114
@@ -8,3 +8,124 @@
8
8
  .chart {
9
9
  position: relative;
10
10
  }
11
+
12
+ .chart--loading #chart {
13
+ visibility: hidden;
14
+ }
15
+
16
+ // Mirrors the cartesian grid in builders.ts (left 40, right 20, top 40, bottom 30)
17
+ .loading {
18
+ position: absolute;
19
+ inset: 0 0 auto;
20
+ pointer-events: none;
21
+
22
+ &--out {
23
+ animation: loading-out .4s ease-out both;
24
+ }
25
+ }
26
+
27
+ // ECharts pads its legend by 5px
28
+ .loading__legend {
29
+ position: absolute;
30
+ top: 7px;
31
+ right: 5px;
32
+ display: flex;
33
+ gap: 12px;
34
+ }
35
+
36
+ .loading__pill {
37
+ display: block;
38
+ height: 10px;
39
+ border-radius: 5px;
40
+ background: var(--zn-skeleton-background, rgb(var(--zn-border-color)));
41
+ }
42
+
43
+ .loading__plot {
44
+ position: absolute;
45
+ inset: 40px 20px 30px 40px;
46
+ display: flex;
47
+ flex-direction: column;
48
+ justify-content: space-between;
49
+ }
50
+
51
+ .loading__row {
52
+ position: relative;
53
+ height: 1px;
54
+ background: rgb(var(--zn-border-color));
55
+ }
56
+
57
+ .loading__label {
58
+ position: absolute;
59
+ right: calc(100% + 8px);
60
+ top: -4px;
61
+ width: 22px;
62
+ height: 8px;
63
+ }
64
+
65
+ .loading__x {
66
+ position: absolute;
67
+ top: calc(100% + 10px);
68
+ left: 0;
69
+ right: 0;
70
+ display: flex;
71
+ justify-content: space-between;
72
+
73
+ .loading__pill {
74
+ width: 44px;
75
+ height: 8px;
76
+ }
77
+ }
78
+
79
+ .loading__track {
80
+ position: relative;
81
+ height: 3px;
82
+ border-radius: 2px;
83
+ background: var(--zn-skeleton-background, rgb(var(--zn-border-color)));
84
+
85
+ .loading__label {
86
+ top: -3px;
87
+ }
88
+
89
+ // Clipped here rather than on the track, which would cut off its axis label
90
+ &::before {
91
+ content: "";
92
+ position: absolute;
93
+ inset: 0;
94
+ border-radius: inherit;
95
+ overflow: hidden;
96
+ background: linear-gradient(90deg, transparent, var(--zn-chart-color-1, rgb(var(--zn-primary))), transparent) no-repeat;
97
+ background-size: 40% 100%;
98
+ }
99
+ }
100
+
101
+ @media (prefers-reduced-motion: no-preference) {
102
+ .loading__row,
103
+ .loading__x,
104
+ .loading__legend .loading__pill {
105
+ animation: loading-pulse 1.4s ease-in-out infinite;
106
+ }
107
+
108
+ .loading__track::before {
109
+ animation: loading-sweep 1.4s ease-in-out infinite;
110
+ }
111
+ }
112
+
113
+ @media (prefers-reduced-motion: reduce) {
114
+ .loading__track::before {
115
+ display: none;
116
+ }
117
+ }
118
+
119
+ @keyframes loading-pulse {
120
+ 0%, 100% { opacity: .4; }
121
+ 50% { opacity: 1; }
122
+ }
123
+
124
+ @keyframes loading-sweep {
125
+ from { background-position: -70% 0; }
126
+ to { background-position: 170% 0; }
127
+ }
128
+
129
+ @keyframes loading-out {
130
+ to { opacity: 0; }
131
+ }
@@ -116,4 +116,85 @@ describe('<zn-chart>', () => {
116
116
  await new Promise((r) => setTimeout(r, 50));
117
117
  expect(a.chart?.group).to.equal('g1');
118
118
  });
119
+
120
+ it('emits zn-chart-click with the clicked point', async () => {
121
+ const el: any = await fixture(html`
122
+ <zn-chart type="bar"
123
+ .data=${[{ name: 'S', data: [1, 2] }]}
124
+ .categories=${['A', 'B']}></zn-chart>
125
+ `);
126
+ await el.updateComplete;
127
+ await new Promise((r) => setTimeout(r, 50));
128
+ let detail: any;
129
+ el.addEventListener('zn-chart-click', (e: CustomEvent) => { detail = e.detail; });
130
+ el.chart.trigger('click', { seriesName: 'S', name: 'B', dataIndex: 1, value: 2 });
131
+ expect(detail).to.deep.equal({ seriesName: 'S', name: 'B', dataIndex: 1, value: 2 });
132
+ });
133
+
134
+ it('uses the theme palette when no colors are given', async () => {
135
+ const el: any = await fixture(html`
136
+ <zn-chart style="--zn-chart-color-1: #010203; --zn-chart-color-2: #040506"
137
+ categories='["a"]' data='[{"name":"s","data":[1]}]'></zn-chart>`);
138
+
139
+ expect(el.getPalette()).to.deep.equal(['#010203', '#040506']);
140
+ });
141
+
142
+ it('prefers explicit colors over the theme palette', async () => {
143
+ const el: any = await fixture(html`<zn-chart style="--zn-chart-color-1: #010203"></zn-chart>`);
144
+ el.colors = ['#ffffff'];
145
+
146
+ expect(el.buildOption().color).to.deep.equal(['#ffffff']);
147
+ });
148
+
149
+ it('fetches data-url once without live, taking categories and data from the response', async () => {
150
+ const original = window.fetch;
151
+ const calls: RequestInit[] = [];
152
+ window.fetch = ((_url: string, init: RequestInit) => {
153
+ calls.push(init);
154
+ return Promise.resolve(new Response(JSON.stringify({categories: ['a', 'b'], data: [{name: 'Sent', data: [1, 2]}]})));
155
+ }) as any;
156
+
157
+ try {
158
+ const el: any = await fixture(html`<zn-chart type="line" data-url="/metrics/chart"></zn-chart>`);
159
+ await el.initPromise;
160
+ await new Promise(r => setTimeout(r, 50));
161
+ await el.updateComplete;
162
+
163
+ expect(calls.length).to.equal(1);
164
+ expect((calls[0].headers as Record<string, string>)['x-kx-fetch-style']).to.equal('raw-json');
165
+ expect(el.categories).to.deep.equal(['a', 'b']);
166
+ expect(el.chart.getOption().series[0].data).to.deep.equal([1, 2]);
167
+ expect(el.chart.getOption().yAxis[0].max).to.not.equal(6);
168
+
169
+ await new Promise(r => setTimeout(r, 1200));
170
+ expect(calls.length).to.equal(1);
171
+ } finally {
172
+ window.fetch = original;
173
+ }
174
+ });
175
+
176
+ it('shows a placeholder until data-url loads', async () => {
177
+ const original = window.fetch;
178
+ let resolve!: (r: Response) => void;
179
+ window.fetch = (() => new Promise<Response>(r => { resolve = r; })) as any;
180
+
181
+ try {
182
+ const el: any = await fixture(html`<zn-chart type="line" data-url="/metrics/chart"></zn-chart>`);
183
+ await el.initPromise;
184
+ expect(el.shadowRoot.querySelector('.loading')).to.exist;
185
+ expect(el.shadowRoot.querySelector('.chart--loading')).to.exist;
186
+
187
+ resolve(new Response(JSON.stringify([{name: 'Sent', data: [1, 2]}])));
188
+ await new Promise(r => setTimeout(r, 50));
189
+ await el.updateComplete;
190
+ expect(el.shadowRoot.querySelector('.chart--loading')).to.not.exist;
191
+ expect(el.chart.getOption().series[0].data).to.deep.equal([1, 2]);
192
+
193
+ await new Promise(r => setTimeout(r, 450));
194
+ await el.updateComplete;
195
+ expect(el.shadowRoot.querySelector('.loading')).to.not.exist;
196
+ } finally {
197
+ window.fetch = original;
198
+ }
199
+ });
119
200
  });
@@ -25,6 +25,7 @@ export type ChatMessageActionType = '' | 'connected.agent' | 'attachment.added'
25
25
  * @slot badge - Rendered in the header after the sender and time (e.g. an INTERNAL NOTE chip).
26
26
  * @slot attachments - Attachments displayed beneath the message content. Use `zn-chat-message-attachment`,
27
27
  * which auto-assigns itself to this slot.
28
+ * @slot footer - Content beneath the bubble, such as reactions or a thread summary.
28
29
  * @slot edit-dialog-trigger - Action rendered at the end of the bubble (e.g. a remove icon button).
29
30
  * @slot edit-dialog - Pass-through for an associated dialog element.
30
31
  *
@@ -35,6 +36,7 @@ export type ChatMessageActionType = '' | 'connected.agent' | 'attachment.added'
35
36
  * @csspart bubble - The message bubble.
36
37
  * @csspart content - The message content within the bubble.
37
38
  * @csspart attachments - The attachments row beneath the message content.
39
+ * @csspart footer - The row beneath the bubble.
38
40
  * @csspart system-card - The card rendered for system action types.
39
41
  *
40
42
  * @cssproperty --message-background - The bubble's background color.
@@ -86,6 +88,9 @@ export default class ZnChatMessage extends ZincElement {
86
88
  /** Whether any element is assigned to the `attachments` slot — drives the attachments row visibility. */
87
89
  @state() private hasAttachments = false;
88
90
 
91
+ /** Whether any element is assigned to the `footer` slot — drives the footer row visibility. */
92
+ @state() private hasFooter = false;
93
+
89
94
  connectedCallback() {
90
95
  const isContent = !this.actionType || this.actionType === 'internal';
91
96
  const agentInitiated = isContent && this.agentInitiated;
@@ -141,6 +146,12 @@ export default class ZnChatMessage extends ZincElement {
141
146
  <slot name="edit-dialog-trigger"></slot>
142
147
  </div>`}
143
148
  </div>
149
+ <slot
150
+ name="footer"
151
+ part="footer"
152
+ class="message__footer ${this.hasFooter ? 'message__footer--visible' : ''}"
153
+ @slotchange=${this.syncHasFooter}
154
+ ></slot>
144
155
  </div>
145
156
  </div>
146
157
  <slot name="edit-dialog"></slot>
@@ -149,7 +160,11 @@ export default class ZnChatMessage extends ZincElement {
149
160
 
150
161
  protected firstUpdated() {
151
162
  this.syncHasAttachments();
152
- Promise.resolve().then(() => this.syncHasAttachments());
163
+ this.syncHasFooter();
164
+ Promise.resolve().then(() => {
165
+ this.syncHasAttachments();
166
+ this.syncHasFooter();
167
+ });
153
168
  }
154
169
 
155
170
  private handleAttachmentsSlotChange() {
@@ -161,6 +176,11 @@ export default class ZnChatMessage extends ZincElement {
161
176
  this.hasAttachments = !!slot && slot.assignedElements().length > 0;
162
177
  }
163
178
 
179
+ private syncHasFooter() {
180
+ const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name="footer"]');
181
+ this.hasFooter = !!slot && slot.assignedElements().length > 0;
182
+ }
183
+
164
184
  private isSystemMessage() {
165
185
  return ZnChatMessage.SYSTEM_ACTION_TYPES.includes(this.actionType);
166
186
  }
@@ -104,11 +104,11 @@
104
104
  }
105
105
 
106
106
  pre {
107
- background-color: #23241f;
107
+ background-color: var(--zn-code-background, #23241f);
108
108
  border-radius: 3px;
109
109
  margin-block: 5px;
110
110
  padding: 5px 10px;
111
- color: #f8f8f2;
111
+ color: var(--zn-code-color, #f8f8f2);
112
112
  overflow: auto;
113
113
  }
114
114
 
@@ -167,6 +167,17 @@
167
167
  @include wc.text-style(subheading-small);
168
168
  }
169
169
 
170
+ &__footer {
171
+ display: none;
172
+ flex-wrap: wrap;
173
+ align-items: center;
174
+ gap: var(--zn-spacing-x-small);
175
+
176
+ &--visible {
177
+ display: flex;
178
+ }
179
+ }
180
+
170
181
  &__actions {
171
182
  flex-shrink: 0;
172
183
  display: flex;
@@ -16,6 +16,15 @@ describe('<zn-chat-message>', () => {
16
16
  expect(el).to.exist;
17
17
  });
18
18
 
19
+ it('should show the footer row only when content is slotted into it', async () => {
20
+ const empty = await fixture<LitElement>('<zn-chat-message sender="Sam">Hi</zn-chat-message>');
21
+ const filled = await fixture<LitElement>('<zn-chat-message sender="Sam">Hi<span slot="footer">👍 1</span></zn-chat-message>');
22
+ await filled.updateComplete;
23
+
24
+ expect(empty.shadowRoot!.querySelector('.message__footer--visible')).to.be.null;
25
+ expect(filled.shadowRoot!.querySelector('.message__footer--visible')).to.exist;
26
+ });
27
+
19
28
  it('should render formatting and blocks chat styles', async () => {
20
29
  const content = await messageContent('<p><strong>Hi</strong></p><pre>code</pre><blockquote>quoted</blockquote>');
21
30
 
@@ -1,3 +1,4 @@
1
+ import {animateTo, EASE_OUT} from "../../internal/animate";
1
2
  import {classMap} from "lit/directives/class-map.js";
2
3
  import {type CSSResultGroup, html, unsafeCSS} from 'lit';
3
4
  import {defaultValue} from "../../internal/default-value";
@@ -5,6 +6,7 @@ import {FormControlController} from "../../internal/form";
5
6
  import {HasSlotController} from "../../internal/slot";
6
7
  import {ifDefined} from "lit/directives/if-defined.js";
7
8
  import {live} from "lit/directives/live.js";
9
+ import {PointerIntentController} from "../../internal/pointer-intent";
8
10
  import {property, query, state} from 'lit/decorators.js';
9
11
  import {watch} from '../../internal/watch';
10
12
  import ZincElement from '../../internal/zinc-element';
@@ -71,8 +73,10 @@ export default class ZnCheckbox extends ZincElement implements ZincFormControl {
71
73
  setValue: (control: ZnCheckbox, checked: boolean) => (control.checked = checked)
72
74
  });
73
75
  private readonly hasSlotController = new HasSlotController(this, '[default]', 'description', 'image');
76
+ private readonly pointerIntent = new PointerIntentController(this);
74
77
 
75
78
  @query('input[type="checkbox"]') input: HTMLInputElement;
79
+ @query('.checkbox__control') control: HTMLElement;
76
80
 
77
81
  @state() private hasFocus = false;
78
82
 
@@ -111,6 +115,9 @@ export default class ZnCheckbox extends ZincElement implements ZincFormControl {
111
115
  /** Squares off the corners of the container drawn by `contained`, which is rounded by default. */
112
116
  @property({type: Boolean, reflect: true}) square = false;
113
117
 
118
+ /** Centres the text of a contained checkbox that has no image or `card-title`. */
119
+ @property({type: Boolean, reflect: true}) centered = false;
120
+
114
121
  /** URL for the image shown in a contained checkbox. */
115
122
  @property() src = '';
116
123
 
@@ -121,8 +128,8 @@ export default class ZnCheckbox extends ZincElement implements ZincFormControl {
121
128
  @property({attribute: 'image-position', reflect: true}) imagePosition: SelectionCardImagePosition = 'left';
122
129
 
123
130
  /**
124
- * Places the checkbox indicator within a contained card. Use `none` to hide the indicator so the card itself
125
- * shows the selected state. Requires `contained`.
131
+ * Places the checkbox indicator within a contained card. A contained checkbox without an image or `card-title` hides it
132
+ * at `start`, as does `none`. Requires `contained`.
126
133
  */
127
134
  @property({attribute: 'control-position', reflect: true}) controlPosition: SelectionCardControlPosition = 'start';
128
135
 
@@ -158,7 +165,7 @@ export default class ZnCheckbox extends ZincElement implements ZincFormControl {
158
165
  /** The icon to show when the checkbox is checked. */
159
166
  @property({attribute: 'checked-icon'}) checkedIcon = '';
160
167
 
161
- /** The icon to show when the checkbox is unchecked. */
168
+ /** The icon to show when the checkbox is unchecked. Defaults to a muted `checked-icon`. */
162
169
  @property({attribute: 'unchecked-icon'}) uncheckedIcon = '';
163
170
 
164
171
  /** The color of the checkbox. */
@@ -234,10 +241,35 @@ export default class ZnCheckbox extends ZincElement implements ZincFormControl {
234
241
  }
235
242
 
236
243
  @watch(['checked', 'indeterminate'], {waitUntilFirstUpdate: true})
237
- handleStateChange() {
244
+ async handleStateChange() {
238
245
  this.input.checked = this.checked; // force a sync update
239
246
  this.input.indeterminate = this.indeterminate; // force a sync update
240
247
  this.formControlController.updateValidity();
248
+
249
+ const animate = this.pointerIntent.consume();
250
+ await this.updateComplete;
251
+ if (!animate) {
252
+ return;
253
+ }
254
+
255
+ animateTo(this.control, [{scale: '0.9'}, {scale: '1'}], {duration: 160, easing: EASE_OUT});
256
+
257
+ const tick = this.control.querySelector('.checkbox__checked-icon');
258
+ if (tick) {
259
+ animateTo(tick, [{strokeDashoffset: 12}, {strokeDashoffset: 0}], {duration: 180, delay: 40, easing: EASE_OUT, fill: 'backwards'});
260
+ }
261
+
262
+ if (this.uncheckedIcon && this.uncheckedIcon !== this.checkedIcon && !this.indeterminate) {
263
+ animateTo(this.control.querySelector('.checkbox__icon')!, [
264
+ {scale: '0.6', opacity: 0},
265
+ {scale: '1', opacity: 1}
266
+ ], {duration: 180, easing: EASE_OUT});
267
+ }
268
+
269
+ const bar = this.control.querySelector('.checkbox__indeterminate-icon');
270
+ if (bar) {
271
+ animateTo(bar, [{scale: '0 1'}, {scale: '1 1'}], {duration: 160, easing: EASE_OUT});
272
+ }
241
273
  }
242
274
 
243
275
  /** Simulates a click on the checkbox. */
@@ -290,6 +322,8 @@ export default class ZnCheckbox extends ZincElement implements ZincFormControl {
290
322
  const hasLabel = this.label || hasLabelSlot;
291
323
 
292
324
  // Determine the effective color
325
+ const hasCustomIcon = Boolean(this.checkedIcon || this.uncheckedIcon);
326
+ const customIconSize = {small: 16, medium: 20, large: 24}[this.size];
293
327
  const effectiveColor = (this.checked || this.indeterminate)
294
328
  ? (this.checkedColor || this.color)
295
329
  : (this.uncheckedColor || this.color);
@@ -336,6 +370,7 @@ export default class ZnCheckbox extends ZincElement implements ZincFormControl {
336
370
  'checkbox--focused': this.hasFocus,
337
371
  'checkbox--indeterminate': this.indeterminate,
338
372
  'checkbox--contained': this.contained,
373
+ 'checkbox--custom-icon': hasCustomIcon,
339
374
  'checkbox--no-border': this.borderless,
340
375
  'checkbox--horizontal': this.horizontal,
341
376
  'checkbox--small': this.size === 'small',
@@ -384,34 +419,33 @@ export default class ZnCheckbox extends ZincElement implements ZincFormControl {
384
419
  ${this.checked && !this.indeterminate
385
420
  ? this.checkedIcon
386
421
  ? html`
387
- <zn-icon part="checked-icon" class="checkbox__icon" src="${this.checkedIcon}"></zn-icon>`
422
+ <zn-icon part="checked-icon" class="checkbox__icon" src="${this.checkedIcon}"
423
+ size="${customIconSize}"></zn-icon>`
388
424
  : html`
389
- <svg viewBox="0 0 24 24"
425
+ <svg viewBox="0 0 16 16"
390
426
  fill="none"
391
427
  stroke="currentColor"
392
- stroke-width="4"
393
- stroke-linecap="round"
394
- stroke-linejoin="round"
428
+ stroke-width="2"
395
429
  class="svg-icon">
396
- <polyline class="checkbox__checked-icon" points="20 6 9 17 4 12"></polyline>
430
+ <polyline class="checkbox__checked-icon" points="4 7.8 6.9 10.6 12 5.4"></polyline>
397
431
  </svg>`
398
432
  : ''}
399
433
 
400
- ${!this.checked && !this.indeterminate && this.uncheckedIcon
434
+ ${!this.checked && !this.indeterminate && hasCustomIcon
401
435
  ? html`
402
- <zn-icon part="unchecked-icon" class="checkbox__icon" src="${this.uncheckedIcon}"></zn-icon>`
436
+ <zn-icon part="unchecked-icon" class="checkbox__icon" src="${this.uncheckedIcon || this.checkedIcon}"
437
+ size="${customIconSize}"></zn-icon>`
403
438
  : ''}
404
439
 
405
440
  ${!this.checked && this.indeterminate
406
441
  ? html`
407
- <svg viewBox="0 0 24 24"
442
+ <svg viewBox="0 0 16 16"
408
443
  fill="none"
409
444
  stroke="currentColor"
410
- stroke-width="4"
411
- stroke-linecap="round"
445
+ stroke-width="2"
412
446
  part="indeterminate-icon"
413
447
  class="checkbox__indeterminate-icon">
414
- <line x1="5" y1="12" x2="19" y2="12"></line>
448
+ <line x1="4" y1="8" x2="12" y2="8"></line>
415
449
  </svg>`
416
450
  : ''}
417
451
  </span>
@@ -427,7 +461,8 @@ export default class ZnCheckbox extends ZincElement implements ZincFormControl {
427
461
  </span>`
428
462
  : ''}
429
463
 
430
- <div part="label" class="checkbox__label selection-card__content">
464
+ <div part="label" class="checkbox__label selection-card__content"
465
+ ?hidden=${!hasDefaultSlot && !this.cardTitle && !hasDescription}>
431
466
  <span part="card-title" class="selection-card__title">
432
467
  <slot></slot>${hasDefaultSlot ? '' : this.cardTitle}
433
468
  </span>
@@ -438,16 +473,15 @@ export default class ZnCheckbox extends ZincElement implements ZincFormControl {
438
473
  part="description">
439
474
  <slot name="description">${this.description}</slot>
440
475
  </div>
441
- ${this.checked
442
- ? html`
443
- <zn-animation name="fadeIn" easing="ease" duration="300" iterations="1" play>
444
- <slot
445
- name="selected-content"
446
- part="selected-content"
447
- class="checkbox__selected-content"
448
- @click=${this.handleSelectedContentClick}></slot>
449
- </zn-animation>`
450
- : ''}
476
+ <div class="checkbox__selected-content-wrapper">
477
+ <div class="checkbox__selected-content-inner">
478
+ <slot
479
+ name="selected-content"
480
+ part="selected-content"
481
+ class="checkbox__selected-content"
482
+ @click=${this.handleSelectedContentClick}></slot>
483
+ </div>
484
+ </div>
451
485
  </div>
452
486
  </label>
453
487
  </div>
@@ -112,7 +112,7 @@
112
112
  justify-content: center;
113
113
  width: var(--toggle-size);
114
114
  height: var(--toggle-size);
115
- border: solid var(--zn-input-border-width) var(--checkbox-border-color);
115
+ border: solid var(--zn-checkbox-border-width, var(--zn-input-border-width)) var(--checkbox-border-color);
116
116
  background-color: var(--checkbox-bg-color);
117
117
  border-radius: var(--zn-border-radius-small);
118
118
  color: var(--checkbox-icon-color);
@@ -131,18 +131,18 @@
131
131
  }
132
132
 
133
133
  .checkbox__indeterminate-icon {
134
- height: max(16px, 70%);
134
+ width: 100%;
135
+ height: 100%;
135
136
  color: var(--checkbox-icon-color);
136
137
  }
137
138
 
138
139
  .svg-icon {
139
- height: max(16px, 70%);
140
+ width: 100%;
141
+ height: 100%;
140
142
  --icon-color: var(--checkbox-icon-color);
141
143
 
142
144
  .checkbox__checked-icon {
143
- stroke-dasharray: 24;
144
- stroke-dashoffset: 24;
145
- transition: stroke-dashoffset 0.4s cubic-bezier(0.4, 0, 0.2, 1);
145
+ stroke-dasharray: 12;
146
146
  }
147
147
  }
148
148
 
@@ -154,10 +154,6 @@
154
154
  .svg-icon {
155
155
  color: var(--checkbox-icon-color);
156
156
  }
157
-
158
- .checkbox__checked-icon {
159
- stroke-dashoffset: 0;
160
- }
161
157
  }
162
158
 
163
159
  /* Hover */
@@ -201,14 +197,6 @@
201
197
  cursor: not-allowed;
202
198
  }
203
199
 
204
- :host-context([required]) .checkbox__label::after {
205
- display: none;
206
- }
207
-
208
- :host([required]) .checkbox__label::after {
209
- display: none;
210
- }
211
-
212
200
  /* If parent Checkbox Group has 'data-user-invalid', style all checkboxes in the group as 'data-user-invalid' by targeting with a class ('checkbox-user-invalid'), since the checkboxes can't be targeted using ::slotted */
213
201
  :host(.checkbox-user-invalid) .checkbox__control {
214
202
  border-color: var(--zn-color-danger-600);
@@ -237,6 +225,12 @@
237
225
 
238
226
  .checkbox__label {
239
227
  display: inline-block;
228
+
229
+ // Without a label, its margin would sit the box off-centre
230
+ &[hidden] {
231
+ display: none;
232
+ }
233
+
240
234
  color: var(--zn-input-label-color);
241
235
  line-height: var(--toggle-size);
242
236
  margin-inline-start: 0.75em;
@@ -255,18 +249,31 @@
255
249
  padding: 1.375rem var(--zn-spacing-large) 1.375rem var(--zn-spacing-medium);
256
250
  border: 1px solid var(--zn-color-gray-400);
257
251
  border-radius: var(--zn-border-radius);
252
+ // A transparent outline from the start lets the checked outline fade in rather than pop.
253
+ outline: 1px solid transparent;
258
254
  width: 100%;
259
255
  height: 100%;
256
+ transition: background-color var(--zn-transition-fast) ease-out,
257
+ border-color var(--zn-transition-fast) ease-out,
258
+ outline-color var(--zn-transition-fast) ease-out,
259
+ scale var(--zn-transition-fast) var(--zn-ease-out);
260
+
261
+ .checkbox__label {
262
+ transition: color var(--zn-transition-fast) ease-out;
263
+ }
260
264
  }
261
265
 
262
266
  :not(.checkbox--disabled).checkbox--contained:hover,
263
267
  :not(.checkbox--disabled).checkbox--contained.checkbox--checked:hover {
264
- background-color: var(--zn-color-purple-50);
265
- transition: var(--zn-transition-medium) all;
268
+ background-color: var(--zn-selection-card-hover-background, var(--zn-color-purple-50));
269
+ }
270
+
271
+ :not(.checkbox--disabled).checkbox--contained:active {
272
+ scale: 0.99;
266
273
  }
267
274
 
268
275
  .checkbox--contained.checkbox--checked .checkbox__label {
269
- color: var(--zn-color-purple-600);
276
+ color: var(--zn-selection-card-checked-color, var(--zn-color-purple-600));
270
277
  font-weight: var(--zn-font-weight-semibold);
271
278
  }
272
279
 
@@ -276,10 +283,9 @@
276
283
  }
277
284
 
278
285
  .checkbox--contained.checkbox--checked {
279
- background-color: var(--zn-color-purple-100);
280
- border: 1px solid var(--zn-color-purple-600);
281
- outline: 1px solid var(--zn-color-purple-600);
282
- transition: var(--zn-transition-medium) all;
286
+ background-color: var(--zn-selection-card-checked-background, var(--zn-color-purple-100));
287
+ border-color: var(--zn-selection-card-checked-color, var(--zn-color-purple-600));
288
+ outline-color: var(--zn-selection-card-checked-color, var(--zn-color-purple-600));
283
289
  }
284
290
 
285
291
  /** Select prefix slot */
@@ -331,3 +337,30 @@
331
337
  color: var(--zn-color-neutral-0);
332
338
  }
333
339
  }
340
+
341
+ /* Custom icons replace the box, so the icon's colour carries the state */
342
+ .checkbox--custom-icon .checkbox__control {
343
+ border-color: transparent !important;
344
+ background-color: transparent !important;
345
+ color: var(--zn-color-neutral-500);
346
+ }
347
+
348
+ .checkbox--custom-icon:not(.checkbox--checked):not(.checkbox--disabled) .checkbox__control:hover {
349
+ color: var(--checkbox-color-hover);
350
+ }
351
+
352
+ .checkbox--custom-icon.checkbox--checked .checkbox__control {
353
+ color: var(--checkbox-color);
354
+ }
355
+
356
+ @include wc.selected-content-reveal(checkbox);
357
+
358
+ /* Icon and SVG card images take the card's state colour */
359
+ .checkbox--contained .selection-card__image-container {
360
+ color: var(--zn-color-gray-500);
361
+ transition: color var(--zn-transition-fast) ease-out;
362
+ }
363
+
364
+ .checkbox--contained.checkbox--checked .selection-card__image-container {
365
+ color: var(--zn-selection-card-checked-color, var(--zn-color-purple-600));
366
+ }