@kubex/zinc 1.1.185 → 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 (358) 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 +9998 -2345
  6. package/dist/vscode.html-custom-data.json +1022 -67
  7. package/dist/web-types.json +2129 -177
  8. package/dist/zn.d.ts +2293 -416
  9. package/dist/zn.min.css +1 -1
  10. package/dist/zn.min.js +2310 -1637
  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/icon.md +46 -1
  33. package/docs/pages/components/input.md +30 -11
  34. package/docs/pages/components/item.md +35 -0
  35. package/docs/pages/components/key-value.md +25 -0
  36. package/docs/pages/components/menu.md +74 -7
  37. package/docs/pages/components/nav-item.md +15 -0
  38. package/docs/pages/components/nav-list.md +132 -0
  39. package/docs/pages/components/navbar.md +100 -1
  40. package/docs/pages/components/page.md +242 -74
  41. package/docs/pages/components/priority-list.md +43 -5
  42. package/docs/pages/components/query-builder.md +23 -0
  43. package/docs/pages/components/radio-group.md +33 -1
  44. package/docs/pages/components/radio.md +1 -1
  45. package/docs/pages/components/report-table.md +202 -0
  46. package/docs/pages/components/stat.md +30 -0
  47. package/docs/pages/components/tile.md +11 -0
  48. package/docs/pages/components/tooltip.md +1 -1
  49. package/docs/pages/components/translation-grid.md +86 -0
  50. package/docs/pages/components/vertical-stepper.md +108 -64
  51. package/package.json +2 -1
  52. package/scss/_global-spacing.scss +2 -2
  53. package/scss/_root.scss +11 -171
  54. package/scss/boot.scss +14 -0
  55. package/scss/mixins/_helper-mixins.scss +24 -2
  56. package/scss/mixins/_motion-mixins.scss +126 -0
  57. package/scss/mixins/_spacing-mixins.scss +4 -3
  58. package/scss/mixins/_tab-indicator-mixins.scss +12 -0
  59. package/scss/mixins/_typography-mixins.scss +1 -1
  60. package/scss/mixins/index.scss +14 -0
  61. package/scss/shared/_base.scss +32 -1
  62. package/scss/shared/_button-mixin.scss +7 -5
  63. package/scss/shared/_table.scss +35 -4
  64. package/scss/shared/nav.scss +4 -0
  65. package/scss/shared/shimmer.scss +1 -1
  66. package/scss/table-controls.scss +206 -0
  67. package/scss/themes/_dark.scss +1 -3
  68. package/scss/themes/_index.scss +1 -1
  69. package/scss/themes/_light.scss +46 -6
  70. package/scss/themes/_modes.scss +11 -11
  71. package/scss/themes/_openbyte.scss +944 -0
  72. package/scss/themes/_typography.scss +4 -2
  73. package/scss/variables/index.scss +0 -9
  74. package/src/components/alert/alert.component.ts +14 -4
  75. package/src/components/alert/alert.scss +55 -69
  76. package/src/components/alert/alert.test.ts +8 -0
  77. package/src/components/animated-button/animated-button.component.ts +3 -2
  78. package/src/components/animated-button/animated-button.scss +6 -23
  79. package/src/components/animated-button/animated-button.test.ts +4 -3
  80. package/src/components/avatar-group/avatar-group.component.ts +84 -0
  81. package/src/components/avatar-group/avatar-group.scss +54 -0
  82. package/src/components/avatar-group/avatar-group.test.ts +59 -0
  83. package/src/components/avatar-group/index.ts +12 -0
  84. package/src/components/badge/badge.component.ts +49 -0
  85. package/src/components/badge/badge.scss +80 -0
  86. package/src/components/badge/badge.test.ts +34 -0
  87. package/src/components/badge/index.ts +12 -0
  88. package/src/components/bulk-actions/bulk-actions.component.ts +14 -2
  89. package/src/components/button/button.component.ts +228 -8
  90. package/src/components/button/button.scss +115 -32
  91. package/src/components/button/button.test.ts +122 -0
  92. package/src/components/button-menu/button-menu.component.ts +32 -11
  93. package/src/components/button-menu/button-menu.scss +5 -1
  94. package/src/components/channel-tile/channel-tile.component.ts +34 -27
  95. package/src/components/channel-tile/channel-tile.scss +76 -43
  96. package/src/components/chart/builders.test.ts +46 -0
  97. package/src/components/chart/builders.ts +27 -3
  98. package/src/components/chart/chart-live.test.ts +4 -6
  99. package/src/components/chart/chart.component.ts +125 -5
  100. package/src/components/chart/chart.scss +121 -0
  101. package/src/components/chart/chart.test.ts +81 -0
  102. package/src/components/chat-message/chat-message.component.ts +21 -1
  103. package/src/components/chat-message/chat-message.scss +13 -2
  104. package/src/components/chat-message/chat-message.test.ts +9 -0
  105. package/src/components/checkbox/checkbox.component.ts +61 -27
  106. package/src/components/checkbox/checkbox.scss +58 -25
  107. package/src/components/checkbox-group/checkbox-group.component.ts +7 -1
  108. package/src/components/chip/chip.component.ts +11 -1
  109. package/src/components/chip/chip.scss +91 -26
  110. package/src/components/chip/chip.test.ts +17 -0
  111. package/src/components/collapsible/collapsible.component.ts +17 -3
  112. package/src/components/collapsible/collapsible.scss +19 -10
  113. package/src/components/color-picker/color-picker.component.ts +277 -0
  114. package/src/components/color-picker/color-picker.scss +141 -0
  115. package/src/components/color-picker/color-picker.test.ts +57 -0
  116. package/src/components/color-picker/index.ts +12 -0
  117. package/src/components/cols/cols.component.ts +10 -0
  118. package/src/components/cols/cols.test.ts +17 -0
  119. package/src/components/confirm/confirm.component.ts +20 -6
  120. package/src/components/confirm/confirm.test.ts +52 -0
  121. package/src/components/content-block/content-block.component.ts +38 -9
  122. package/src/components/content-block/content-block.scss +11 -5
  123. package/src/components/content-block/content-block.test.ts +26 -0
  124. package/src/components/copy-button/copy-button.component.ts +2 -2
  125. package/src/components/copy-button/copy-button.scss +17 -4
  126. package/src/components/data-select/data-select.component.ts +3 -1
  127. package/src/components/data-table/data-table.component.ts +362 -140
  128. package/src/components/data-table/data-table.scss +133 -60
  129. package/src/components/data-table/data-table.test.ts +356 -4
  130. package/src/components/data-table-filter/data-table-filter.component.ts +426 -406
  131. package/src/components/data-table-filter/data-table-filter.scss +176 -148
  132. package/src/components/data-table-filter/data-table-filter.test.ts +271 -273
  133. package/src/components/data-table-search/data-table-search.component.ts +4 -2
  134. package/src/components/data-table-search/data-table-search.scss +8 -1
  135. package/src/components/data-table-search/data-table-search.test.ts +29 -0
  136. package/src/components/date-range/date-range-math.test.ts +78 -0
  137. package/src/components/date-range/date-range-math.ts +105 -0
  138. package/src/components/date-range/date-range.component.ts +375 -0
  139. package/src/components/date-range/date-range.scss +272 -0
  140. package/src/components/date-range/date-range.test.ts +247 -0
  141. package/src/components/date-range/index.ts +12 -0
  142. package/src/components/datepicker/datepicker.component.ts +44 -7
  143. package/src/components/datepicker/datepicker.scss +9 -0
  144. package/src/components/datepicker/datepicker.test.ts +2 -2
  145. package/src/components/dialog/dialog.component.ts +38 -19
  146. package/src/components/dialog/dialog.scss +65 -36
  147. package/src/components/dialog/dialog.test.ts +14 -0
  148. package/src/components/diff/diff.component.ts +55 -0
  149. package/src/components/diff/diff.scss +46 -0
  150. package/src/components/diff/diff.test.ts +15 -0
  151. package/src/components/diff/index.ts +12 -0
  152. package/src/components/diff-row/diff-row.component.ts +75 -0
  153. package/src/components/diff-row/diff-row.scss +70 -0
  154. package/src/components/diff-row/diff-row.test.ts +37 -0
  155. package/src/components/diff-row/index.ts +12 -0
  156. package/src/components/dropdown/dropdown.component.ts +12 -10
  157. package/src/components/dropdown/dropdown.scss +2 -0
  158. package/src/components/editor/editor.component.ts +159 -11
  159. package/src/components/editor/editor.scss +250 -1
  160. package/src/components/editor/editor.test.ts +31 -3
  161. package/src/components/editor/modules/ai/panel/ai-panel.scss +0 -1
  162. package/src/components/editor/modules/attachment/attachment.ts +53 -31
  163. package/src/components/editor/modules/context-menu/context-menu.ts +17 -0
  164. package/src/components/editor/modules/dialog/dialog.component.ts +23 -1
  165. package/src/components/editor/modules/dialog/dialog.test.ts +28 -0
  166. package/src/components/editor/modules/emoji/emoji.ts +4 -5
  167. package/src/components/editor/modules/merge-field/merge-field.ts +83 -0
  168. package/src/components/editor/modules/toolbar/toolbar.component.ts +121 -68
  169. package/src/components/editor/modules/toolbar/toolbar.scss +38 -0
  170. package/src/components/editor/modules/toolbar/toolbar.ts +25 -1
  171. package/src/components/empty-state/empty-state.component.ts +6 -1
  172. package/src/components/empty-state/empty-state.scss +21 -4
  173. package/src/components/expanding-action/expanding-action.component.ts +22 -34
  174. package/src/components/expanding-action/expanding-action.scss +3 -45
  175. package/src/components/expanding-action/expanding-action.test.ts +2 -1
  176. package/src/components/file/file.component.ts +30 -2
  177. package/src/components/file/file.scss +6 -0
  178. package/src/components/flow-builder/flow-builder.component.ts +36 -3
  179. package/src/components/flow-builder/flow-builder.scss +0 -6
  180. package/src/components/flow-builder/modules/flow-canvas/flow-canvas.component.ts +8 -0
  181. package/src/components/flow-builder/modules/flow-canvas/flow-canvas.scss +10 -5
  182. package/src/components/flow-builder/modules/flow-node/flow-node.component.ts +17 -0
  183. package/src/components/flow-builder/modules/flow-node/flow-node.scss +10 -0
  184. package/src/components/form-actions/form-actions.component.ts +48 -2
  185. package/src/components/form-actions/form-actions.scss +1 -1
  186. package/src/components/form-group/form-group.component.ts +10 -3
  187. package/src/components/form-group/form-group.scss +37 -4
  188. package/src/components/form-group/form-group.test.ts +10 -0
  189. package/src/components/header/header.component.ts +11 -4
  190. package/src/components/header/header.scss +47 -5
  191. package/src/components/hover-container/hover-container.component.ts +4 -5
  192. package/src/components/icon/icon.component.ts +95 -9
  193. package/src/components/icon/icon.scss +70 -6
  194. package/src/components/icon/icon.test.ts +55 -0
  195. package/src/components/icon-picker/icon-picker.component.ts +35 -1
  196. package/src/components/inline-edit/inline-edit.component.ts +38 -8
  197. package/src/components/inline-edit/inline-edit.scss +128 -19
  198. package/src/components/input/input.component.ts +173 -297
  199. package/src/components/input/input.scss +65 -43
  200. package/src/components/input/input.test.ts +86 -4
  201. package/src/components/item/item.component.ts +12 -0
  202. package/src/components/item/item.scss +102 -3
  203. package/src/components/item/item.test.ts +23 -0
  204. package/src/components/key/key.component.ts +2 -2
  205. package/src/components/key/key.scss +11 -0
  206. package/src/components/key-value/index.ts +12 -0
  207. package/src/components/key-value/key-value.component.ts +160 -0
  208. package/src/components/key-value/key-value.scss +20 -0
  209. package/src/components/key-value/key-value.test.ts +22 -0
  210. package/src/components/markdown-editor/markdown-editor.component.ts +8 -1
  211. package/src/components/menu/menu.component.ts +21 -2
  212. package/src/components/menu/menu.scss +43 -23
  213. package/src/components/menu/menu.test.ts +33 -0
  214. package/src/components/menu-item/menu-item.component.ts +13 -2
  215. package/src/components/menu-item/menu-item.scss +56 -23
  216. package/src/components/menu-item/menu-item.test.ts +31 -0
  217. package/src/components/menu-item/submenu-controller.ts +25 -15
  218. package/src/components/menu-label/index.ts +12 -0
  219. package/src/components/menu-label/menu-label.component.ts +30 -0
  220. package/src/components/menu-label/menu-label.scss +18 -0
  221. package/src/components/nav-item/index.ts +12 -0
  222. package/src/components/nav-item/nav-item.component.ts +83 -0
  223. package/src/components/nav-item/nav-item.scss +128 -0
  224. package/src/components/nav-list/index.ts +12 -0
  225. package/src/components/nav-list/nav-list.component.ts +313 -0
  226. package/src/components/nav-list/nav-list.scss +87 -0
  227. package/src/components/nav-list/nav-list.test.ts +250 -0
  228. package/src/components/navbar/navbar.component.ts +235 -171
  229. package/src/components/navbar/navbar.scss +333 -169
  230. package/src/components/navbar/navbar.test.ts +63 -143
  231. package/src/components/page/page.component.ts +114 -29
  232. package/src/components/page/page.scss +223 -95
  233. package/src/components/page/page.test.ts +214 -3
  234. package/src/components/page-builder/page-builder.component.ts +51 -5
  235. package/src/components/page-builder/page-builder.scss +6 -1
  236. package/src/components/page-nav/page-nav.component.ts +25 -3
  237. package/src/components/page-nav/page-nav.scss +10 -2
  238. package/src/components/pagination/pagination.scss +1 -1
  239. package/src/components/panel/panel.component.ts +14 -13
  240. package/src/components/panel/panel.scss +14 -10
  241. package/src/components/panel/panel.test.ts +42 -0
  242. package/src/components/popup/popup.component.ts +20 -13
  243. package/src/components/popup/popup.test.ts +21 -1
  244. package/src/components/priority-list/priority-list.component.ts +157 -172
  245. package/src/components/priority-list/priority-list.scss +113 -17
  246. package/src/components/priority-list/priority-list.test.ts +301 -3
  247. package/src/components/progress-bar/progress-bar.component.ts +1 -1
  248. package/src/components/progress-bar/progress-bar.scss +16 -4
  249. package/src/components/progress-tile/progress-tile.scss +1 -1
  250. package/src/components/query-builder/query-builder.component.ts +85 -10
  251. package/src/components/query-builder/query-builder.scss +7 -1
  252. package/src/components/query-builder/query-builder.test.ts +40 -0
  253. package/src/components/radio/radio.component.ts +57 -18
  254. package/src/components/radio/radio.scss +101 -26
  255. package/src/components/radio-group/radio-group.component.ts +45 -7
  256. package/src/components/radio-group/radio-group.scss +17 -0
  257. package/src/components/radio-group/radio-group.test.ts +63 -2
  258. package/src/components/rating/rating.component.ts +23 -0
  259. package/src/components/rating/rating.scss +1 -1
  260. package/src/components/remarkd-editor/remarkd-editor.component.ts +60 -5
  261. package/src/components/remarkd-editor/remarkd-editor.scss +12 -4
  262. package/src/components/report-table/index.ts +12 -0
  263. package/src/components/report-table/report-format.test.ts +86 -0
  264. package/src/components/report-table/report-format.ts +72 -0
  265. package/src/components/report-table/report-math.test.ts +74 -0
  266. package/src/components/report-table/report-math.ts +252 -0
  267. package/src/components/report-table/report-table.component.ts +681 -0
  268. package/src/components/report-table/report-table.scss +328 -0
  269. package/src/components/report-table/report-table.test.ts +702 -0
  270. package/src/components/reveal/reveal.component.ts +15 -1
  271. package/src/components/reveal/reveal.scss +5 -0
  272. package/src/components/schedule-builder/schedule-builder.component.ts +23 -8
  273. package/src/components/scroll-container/scroll-container.component.ts +19 -1
  274. package/src/components/scroll-container/scroll-container.scss +6 -1
  275. package/src/components/select/select.component.ts +52 -36
  276. package/src/components/select/select.scss +42 -25
  277. package/src/components/select/select.test.ts +14 -2
  278. package/src/components/settings-container/settings-container.scss +18 -5
  279. package/src/components/sidebar/sidebar.component.ts +8 -1
  280. package/src/components/sidebar/sidebar.scss +6 -1
  281. package/src/components/skeleton/skeleton.component.ts +3 -3
  282. package/src/components/skeleton/skeleton.scss +6 -6
  283. package/src/components/skeleton/skeleton.test.ts +9 -0
  284. package/src/components/slash-menu/slash-menu.scss +1 -1
  285. package/src/components/slideout/slideout.component.ts +20 -3
  286. package/src/components/slideout/slideout.scss +13 -6
  287. package/src/components/slideout/slideout.test.ts +19 -0
  288. package/src/components/split-button/split-button.component.ts +1 -1
  289. package/src/components/split-pane/split-pane.component.ts +71 -8
  290. package/src/components/split-pane/split-pane.scss +145 -41
  291. package/src/components/split-pane/split-pane.test.ts +23 -3
  292. package/src/components/stat/stat.component.ts +209 -14
  293. package/src/components/stat/stat.scss +305 -5
  294. package/src/components/stat/stat.test.ts +143 -2
  295. package/src/components/status-indicator/status-indicator.scss +22 -21
  296. package/src/components/stepper/stepper.scss +3 -3
  297. package/src/components/tab/tab.component.ts +1 -0
  298. package/src/components/table/table.component.ts +12 -1
  299. package/src/components/table/table.scss +21 -13
  300. package/src/components/table/table.test.ts +17 -0
  301. package/src/components/tabs/tabs.component.ts +150 -37
  302. package/src/components/tabs/tabs.scss +48 -7
  303. package/src/components/tabs/tabs.test.ts +169 -0
  304. package/src/components/textarea/textarea.component.ts +25 -3
  305. package/src/components/textarea/textarea.scss +10 -0
  306. package/src/components/textarea/textarea.test.ts +8 -4
  307. package/src/components/theme-editor/theme-editor.scss +0 -6
  308. package/src/components/tile/tile.component.ts +32 -2
  309. package/src/components/tile/tile.scss +40 -7
  310. package/src/components/tile/tile.test.ts +10 -0
  311. package/src/components/toggle/toggle.component.ts +23 -7
  312. package/src/components/toggle/toggle.scss +36 -29
  313. package/src/components/toggle/toggle.test.ts +17 -0
  314. package/src/components/tooltip/tooltip.component.ts +3 -0
  315. package/src/components/tooltip/tooltip.scss +11 -6
  316. package/src/components/tooltip/tooltip.test.ts +12 -0
  317. package/src/components/translation-field/index.ts +12 -0
  318. package/src/components/translation-field/translation-field.component.ts +55 -0
  319. package/src/components/translation-field/translation-field.scss +101 -0
  320. package/src/components/translation-fields/index.ts +12 -0
  321. package/src/components/translation-fields/translation-fields.component.ts +80 -0
  322. package/src/components/translation-fields/translation-fields.scss +60 -0
  323. package/src/components/translation-grid/index.ts +12 -0
  324. package/src/components/translation-grid/translation-grid.component.ts +157 -0
  325. package/src/components/translation-grid/translation-grid.scss +138 -0
  326. package/src/components/translation-grid/translation-grid.test.ts +28 -0
  327. package/src/components/vertical-stepper/vertical-stepper.component.ts +35 -9
  328. package/src/components/vertical-stepper/vertical-stepper.scss +110 -39
  329. package/src/components/vertical-stepper/vertical-stepper.test.ts +35 -0
  330. package/src/components/well/well.scss +2 -2
  331. package/src/events/events.ts +2 -0
  332. package/src/events/zn-chart-click.ts +13 -0
  333. package/src/events/zn-report-change.ts +7 -0
  334. package/src/form-control.scss +36 -3
  335. package/src/internal/anchored-popover.ts +175 -0
  336. package/src/internal/animate.ts +19 -5
  337. package/src/internal/cosmic-border.ts +15 -0
  338. package/src/internal/form.ts +1 -1
  339. package/src/internal/hover-intent.ts +15 -0
  340. package/src/internal/input-modality.ts +15 -0
  341. package/src/internal/pointer-intent.ts +37 -0
  342. package/src/internal/reorder.ts +625 -0
  343. package/src/internal/scroll.ts +51 -3
  344. package/src/internal/selection-card.ts +1 -1
  345. package/src/internal/tab-indicator.ts +92 -0
  346. package/src/internal/table-sort.ts +25 -0
  347. package/src/internal/table-tabs.ts +108 -0
  348. package/src/internal/test-drag.ts +35 -0
  349. package/src/internal/theme-openbyte.test.ts +126 -0
  350. package/src/internal/theme.ts +4 -4
  351. package/src/internal/zinc-element.ts +2 -2
  352. package/src/selection-card.scss +25 -0
  353. package/src/types/web-test-runner-commands.d.ts +1 -0
  354. package/src/utilities/color.test.ts +43 -0
  355. package/src/utilities/color.ts +189 -0
  356. package/src/zinc.ts +14 -0
  357. package/.github/workflows/eleventy_build.yml +0 -42
  358. package/scss/themes/_aura.scss +0 -114
@@ -1,5 +1,6 @@
1
1
  import {classMap} from "lit/directives/class-map.js";
2
2
  import {type CSSResultGroup, html, unsafeCSS} from 'lit';
3
+ import {ifDefined} from "lit/directives/if-defined.js";
3
4
  import {property} from 'lit/decorators.js';
4
5
  import ZincElement from '../../internal/zinc-element';
5
6
 
@@ -88,6 +89,13 @@ export default class ZnReveal extends ZincElement {
88
89
  }
89
90
  }
90
91
 
92
+ protected handleKeyDown(e: KeyboardEvent) {
93
+ if (e.key === 'Enter' || e.key === ' ') {
94
+ e.preventDefault();
95
+ this.handleToggleReveal();
96
+ }
97
+ }
98
+
91
99
  protected handleMouseEnter() {
92
100
  // handle hover only while hovered
93
101
  this._clearHideTimer();
@@ -123,9 +131,15 @@ export default class ZnReveal extends ZincElement {
123
131
  'reveal--revealed': this._isRevealed,
124
132
  'reveal--toggled': this._isToggled,
125
133
  })}
134
+ role=${ifDefined(this.noToggle ? undefined : 'button')}
135
+ tabindex=${ifDefined(this.noToggle ? undefined : '0')}
136
+ aria-pressed=${ifDefined(this.noToggle ? undefined : String(this._isToggled))}
126
137
  @click="${this.handleToggleReveal}"
138
+ @keydown="${this.handleKeyDown}"
127
139
  @mouseenter="${this.handleMouseEnter}"
128
- @mouseleave="${this.handleMouseLeave}">
140
+ @mouseleave="${this.handleMouseLeave}"
141
+ @focus="${this.handleMouseEnter}"
142
+ @blur="${this.handleMouseLeave}">
129
143
  <span class="reveal__text reveal__text--initial">${this.initial}</span>
130
144
  <span class="reveal__text reveal__text--revealed">${this.revealed}</span>
131
145
  </div>
@@ -15,6 +15,11 @@
15
15
  // Only a click that toggles earns the pointer: a static or hover-only reveal does nothing on click.
16
16
  .reveal--clickable {
17
17
  cursor: pointer;
18
+
19
+ &:focus-visible {
20
+ outline: var(--zn-focus-ring);
21
+ border-radius: var(--zn-border-radius-small);
22
+ }
18
23
  }
19
24
 
20
25
  // cursor inherits, so a static reveal has to opt out of a clickable container's pointer
@@ -1158,7 +1158,21 @@ export default class ZnScheduleBuilder extends ZincElement implements ZincFormCo
1158
1158
 
1159
1159
  this._commitShownDays({...shown, [day]: ranges});
1160
1160
  // The new range may merge into a neighbour, so find where it actually landed.
1161
- this._editing = {day, index: Math.max(ranges.findIndex(item => item.start === range.start), 0)};
1161
+ void this._openEditor(day, Math.max(ranges.findIndex(item => item.start === range.start), 0));
1162
+ }
1163
+
1164
+ private async _openEditor(day: ScheduleDay, index: number) {
1165
+ this._editing = {day, index};
1166
+ await this.updateComplete;
1167
+ this.shadowRoot?.querySelector<ZnInput>('.list__editor zn-input')?.focus();
1168
+ }
1169
+
1170
+ /** Focuses a day's range chip, clamped to the chips there are; the day's "Add range" button when it has none. */
1171
+ private async _focusRangeChip(day: ScheduleDay, index: number) {
1172
+ await this.updateComplete;
1173
+ const row = this.shadowRoot?.querySelector(`.list__row[data-day="${day}"]`);
1174
+ const chips = row?.querySelectorAll<HTMLElement>('.list__chip') ?? [];
1175
+ (chips[Math.min(index, chips.length - 1)] ?? row?.querySelector<HTMLElement>('.list__add'))?.focus();
1162
1176
  }
1163
1177
 
1164
1178
  private _handleRemoveRange(day: ScheduleDay, index: number) {
@@ -1167,6 +1181,7 @@ export default class ZnScheduleBuilder extends ZincElement implements ZincFormCo
1167
1181
  const shown = this._storedAsShown;
1168
1182
  this._editing = null;
1169
1183
  this._commitShownDays({...shown, [day]: shown[day].filter((_, position) => position !== index)});
1184
+ void this._focusRangeChip(day, index);
1170
1185
  }
1171
1186
 
1172
1187
  private _handleRangeEdit(day: ScheduleDay, index: number, edge: 'start' | 'end', value: string) {
@@ -1186,10 +1201,12 @@ export default class ZnScheduleBuilder extends ZincElement implements ZincFormCo
1186
1201
  }
1187
1202
 
1188
1203
  private _handleEditorKeyDown(event: KeyboardEvent) {
1189
- if (event.key === 'Enter' || event.key === 'Escape') {
1204
+ if ((event.key === 'Enter' || event.key === 'Escape') && this._editing) {
1190
1205
  event.preventDefault();
1191
1206
  event.stopPropagation();
1207
+ const {day, index} = this._editing;
1192
1208
  this._editing = null;
1209
+ void this._focusRangeChip(day, index);
1193
1210
  }
1194
1211
  }
1195
1212
 
@@ -1340,9 +1357,7 @@ export default class ZnScheduleBuilder extends ZincElement implements ZincFormCo
1340
1357
  </div>
1341
1358
 
1342
1359
  <div class="schedule-builder__canvas calendar__canvas"
1343
- role="grid"
1344
- aria-label="Weekly opening hours"
1345
- aria-readonly=${!this._isEditable}
1360
+ aria-hidden="true"
1346
1361
  @pointerdown=${this._handleCanvasPointerDown}
1347
1362
  @pointermove=${this._handleCanvasPointerMove}
1348
1363
  @pointerup=${this._handleCanvasPointerUp}
@@ -1372,7 +1387,7 @@ export default class ZnScheduleBuilder extends ZincElement implements ZincFormCo
1372
1387
  }
1373
1388
 
1374
1389
  return html`
1375
- <div class="calendar__col" role="row" aria-label=${DAY_LABELS[day].long}>${slots}</div>`;
1390
+ <div class="calendar__col">${slots}</div>`;
1376
1391
  }
1377
1392
 
1378
1393
  private _renderSummary(days: ScheduleDayMap) {
@@ -1411,7 +1426,7 @@ export default class ZnScheduleBuilder extends ZincElement implements ZincFormCo
1411
1426
  const note = this._dayNote(day);
1412
1427
 
1413
1428
  return html`
1414
- <div class=${classMap({list__row: true, 'list__row--editing': editing > -1})}>
1429
+ <div class=${classMap({list__row: true, 'list__row--editing': editing > -1})} data-day=${day}>
1415
1430
  <div class=${classMap({list__day: true, 'list__day--closed': ranges.length === 0})}>
1416
1431
  ${DAY_LABELS[day].short}
1417
1432
  </div>
@@ -1443,7 +1458,7 @@ export default class ZnScheduleBuilder extends ZincElement implements ZincFormCo
1443
1458
  class=${classMap({list__chip: true, 'list__chip--reduced': reduced})}
1444
1459
  ?disabled=${!this._isEditable}
1445
1460
  @click=${() => {
1446
- if (this._isEditable) this._editing = {day, index};
1461
+ if (this._isEditable) void this._openEditor(day, index);
1447
1462
  }}>
1448
1463
  ${this._formatRange(range)}
1449
1464
  </button>`;
@@ -39,6 +39,7 @@ export default class ZnScrollContainer extends ZincElement {
39
39
 
40
40
  private _footerObserved: boolean = false;
41
41
  private _footerHeightFrame: number | null = null;
42
+ private _scrollEndTimer: number | null = null;
42
43
 
43
44
  protected firstUpdated(_changedProperties: PropertyValues) {
44
45
  super.firstUpdated(_changedProperties);
@@ -64,6 +65,23 @@ export default class ZnScrollContainer extends ZincElement {
64
65
  cancelAnimationFrame(this._footerHeightFrame);
65
66
  this._footerHeightFrame = null;
66
67
  }
68
+ this._cancelScrollEnd();
69
+ }
70
+
71
+ // Reading scrollHeight forces a layout, so a burst of mutations scrolls once, after it settles.
72
+ private _queueScrollEnd() {
73
+ this._cancelScrollEnd();
74
+ this._scrollEndTimer = window.setTimeout(() => {
75
+ this._scrollEndTimer = null;
76
+ this.scrollEnd();
77
+ }, 100);
78
+ }
79
+
80
+ private _cancelScrollEnd() {
81
+ if (this._scrollEndTimer !== null) {
82
+ clearTimeout(this._scrollEndTimer);
83
+ this._scrollEndTimer = null;
84
+ }
67
85
  }
68
86
 
69
87
  scrollEnd() {
@@ -92,7 +110,7 @@ export default class ZnScrollContainer extends ZincElement {
92
110
  target: null,
93
111
  config: {childList: true, subtree: true},
94
112
  callback: () => {
95
- setTimeout(() => this.scrollEnd(), 100);
113
+ this._queueScrollEnd();
96
114
  if (this.footer) {
97
115
  this._syncFooterHeight();
98
116
  if (!this._footerObserved) {
@@ -36,7 +36,12 @@
36
36
  overflow-y: auto;
37
37
  flex-grow: 1;
38
38
  margin: 0;
39
- padding: 0 0 var(--zn-scroll-footer-height, 0px) 0;
39
+ padding: 0 0 calc(var(--zn-scroll-footer-height, 0px) + var(--zn-pane-end-inset, 0px)) 0;
40
+
41
+ // Only the outermost scroller leaves room for the pane's end
42
+ > * {
43
+ --zn-pane-end-inset: 0px;
44
+ }
40
45
  }
41
46
 
42
47
  .scroll-header {
@@ -1,11 +1,10 @@
1
- import {animateTo, stopAnimations} from '../../internal/animate.js';
2
1
  import {classMap} from "lit/directives/class-map.js";
3
2
  import {ConditionalController} from "../../internal/conditional";
4
3
  import {FormControlController} from "../../internal/form";
5
- import {getAnimation, setDefaultAnimation} from "../../utilities/animation-registry";
6
4
  import {HasSlotController} from "../../internal/slot";
7
5
  import {html, nothing, unsafeCSS} from 'lit';
8
6
  import {LocalizeController} from "../../utilities/localize";
7
+ import {modeSignal, themeSignal} from '../../internal/theme';
9
8
  import {property, query, state} from 'lit/decorators.js';
10
9
  import {scrollIntoView} from "../../internal/scroll";
11
10
  import {unsafeHTML} from "lit/directives/unsafe-html.js";
@@ -97,6 +96,7 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
97
96
  private readonly hasSlotController = new HasSlotController(this, 'help-text', 'label');
98
97
  private readonly localize = new LocalizeController(this);
99
98
  private typeToSelectString = '';
99
+ private escapeSwallowed = false;
100
100
  private typeToSelectTimeout: number;
101
101
  private closeWatcher: CloseWatcher | null;
102
102
 
@@ -319,6 +319,9 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
319
319
  /** The select's required attribute. */
320
320
  @property({type: Boolean, reflect: true}) required = false;
321
321
 
322
+ /** Short text shown next to the label, styled like the help text, e.g. `optional`. */
323
+ @property({attribute: 'label-note'}) labelNote = '';
324
+
322
325
  @property({attribute: 'cache-key'}) cacheKey: string = "";
323
326
 
324
327
  @property({type: Boolean, attribute: 'trigger-submit'}) triggerSubmit = false;
@@ -344,7 +347,11 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
344
347
  ${option.getTextLabel()}
345
348
  ${(!this.nonRemovable) ? html`
346
349
  <zn-icon slot="action" src="close" size="16"
347
- @click=${(e: any) => this.handleTagRemove(e as ZnRemoveEvent, option)}></zn-icon>` : nothing}
350
+ role="button"
351
+ tabindex=${this.disabled ? '-1' : '0'}
352
+ aria-label="Remove ${option.getTextLabel()}"
353
+ @click=${(e: any) => this.handleTagRemove(e as ZnRemoveEvent, option)}
354
+ @keydown=${(e: KeyboardEvent) => this.handleTagRemoveKeyDown(e, option)}></zn-icon>` : nothing}
348
355
  </zn-chip>
349
356
  `;
350
357
  };
@@ -515,13 +522,6 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
515
522
  this.displayInput.focus({preventScroll: true});
516
523
  }
517
524
 
518
- // Blur the display input when Escape is pressed and the dropdown is closed,
519
- // so a second Escape press can bubble (e.g. close a containing dialog).
520
- if (event.key === 'Escape' && !this.open) {
521
- event.stopPropagation();
522
- this.displayInput.blur();
523
- }
524
-
525
525
  // Handle enter and space. When pressing space, we allow for type to select behaviors so if there's anything in the
526
526
  // buffer we _don't_ close it. When search is enabled, space should type into the input, not toggle.
527
527
  if (event.key === 'Enter' || (event.key === ' ' && !this._isTypeable && this.typeToSelectString === '')) {
@@ -723,6 +723,14 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
723
723
  }
724
724
 
725
725
  private handleComboboxKeyDown(event: KeyboardEvent) {
726
+ // The first Escape on a closed select stays here; a repeat bubbles so it can dismiss a containing popup
727
+ if (event.key === 'Escape' && !this.open) {
728
+ if (this.escapeSwallowed) return;
729
+ this.escapeSwallowed = true;
730
+ } else {
731
+ this.escapeSwallowed = false;
732
+ }
733
+
726
734
  if (event.key === 'Tab') {
727
735
  return;
728
736
  }
@@ -1151,7 +1159,17 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
1151
1159
  }
1152
1160
  }
1153
1161
 
1154
- private handleTagRemove(event: ZnRemoveEvent, option: ZnOption) {
1162
+ private handleTagRemoveKeyDown(event: KeyboardEvent, option: ZnOption) {
1163
+ if (event.key !== 'Enter' && event.key !== ' ') return;
1164
+ event.preventDefault();
1165
+
1166
+ const removeButtons = () => [...this.shadowRoot!.querySelectorAll<HTMLElement>('.select__tags zn-icon[slot="action"]')];
1167
+ const index = removeButtons().indexOf(event.currentTarget as HTMLElement);
1168
+ this.handleTagRemove(event, option);
1169
+ this.updateComplete.then(() => (removeButtons()[index] ?? this.displayInput).focus());
1170
+ }
1171
+
1172
+ private handleTagRemove(event: Event, option: ZnOption) {
1155
1173
  event.stopPropagation();
1156
1174
  event.stopImmediatePropagation();
1157
1175
 
@@ -1676,7 +1694,6 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
1676
1694
  this.emit('zn-show');
1677
1695
  this.addOpenListeners();
1678
1696
 
1679
- await stopAnimations(this);
1680
1697
  this.listbox.hidden = false;
1681
1698
  this.popup.active = true;
1682
1699
 
@@ -1692,8 +1709,7 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
1692
1709
  });
1693
1710
  }
1694
1711
 
1695
- const {keyframes, options} = getAnimation(this, 'select.show', {dir: this.localize.dir()});
1696
- await animateTo(this.popup.popup, keyframes, options);
1712
+ await this.popup.updateComplete;
1697
1713
 
1698
1714
  // Make sure the current option is scrolled into view (required for Safari)
1699
1715
  if (this.currentOption) {
@@ -1719,9 +1735,6 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
1719
1735
  this.displayInput.value = this.multiple ? '' : this.displayLabel;
1720
1736
  }
1721
1737
 
1722
- await stopAnimations(this);
1723
- const {keyframes, options} = getAnimation(this, 'select.hide', {dir: this.localize.dir()});
1724
- await animateTo(this.popup.popup, keyframes, options);
1725
1738
  this.listbox.hidden = true;
1726
1739
  this.popup.active = false;
1727
1740
 
@@ -1843,6 +1856,25 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
1843
1856
  }
1844
1857
  }
1845
1858
 
1859
+ // A theme picks the chevron through --zn-select-expand-icon and its size through
1860
+ // --zn-select-expand-icon-size, as zn-icon sizes itself from its size attribute.
1861
+ // Read once per theme and mode: reading styles in render forces a style recalc each time.
1862
+ private _expandIcon?: {key: string; src: string; size: string};
1863
+
1864
+ private expandIcon(): {src: string; size: string} {
1865
+ const key = `${themeSignal.get()}|${modeSignal.get()}`;
1866
+ if (this._expandIcon?.key !== key) {
1867
+ const style = getComputedStyle(this);
1868
+ const src = style.getPropertyValue('--zn-select-expand-icon').trim().replace(/^["']|["']$/g, '');
1869
+ this._expandIcon = {
1870
+ key,
1871
+ src: src || 'keyboard_arrow_down',
1872
+ size: String(parseInt(style.getPropertyValue('--zn-select-expand-icon-size')) || 24),
1873
+ };
1874
+ }
1875
+ return this._expandIcon;
1876
+ }
1877
+
1846
1878
  render() {
1847
1879
  const hasLabelSlot = this.hasSlotController.test('label');
1848
1880
  const hasLabelTooltipSlot = this.hasSlotController.test('label-tooltip');
@@ -1886,6 +1918,7 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
1886
1918
  <zn-icon src="info"></zn-icon>
1887
1919
  </zn-tooltip>`
1888
1920
  : ''}
1921
+ ${this.labelNote ? html`<span class="form-control__label-note">${this.labelNote}</span>` : ''}
1889
1922
  </label>
1890
1923
  ${hasContextNote
1891
1924
  ? html`
@@ -1979,8 +2012,7 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
1979
2012
  type="button"
1980
2013
  aria-label=${this.localize.term('clearEntry')}
1981
2014
  @mousedown=${this.handleClearMouseDown}
1982
- @click=${this.handleClearClick}
1983
- tabindex="-1">
2015
+ @click=${this.handleClearClick}>
1984
2016
  <slot name="clear-icon">
1985
2017
  <zn-icon src="circle-x@lu" size="20"></zn-icon>
1986
2018
  </slot>
@@ -1995,7 +2027,7 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
1995
2027
  <zn-icon src="error" class="select__expand-icon select__fetch-error-icon"></zn-icon>`
1996
2028
  : html`
1997
2029
  <slot name="expand-icon" part="expand-icon" class="select__expand-icon">
1998
- <zn-icon src="keyboard_arrow_down"></zn-icon>
2030
+ <zn-icon src="${this.expandIcon().src}" size="${this.expandIcon().size}"></zn-icon>
1999
2031
  </slot>`
2000
2032
  }
2001
2033
  </div>
@@ -2079,19 +2111,3 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
2079
2111
  `;
2080
2112
  }
2081
2113
  }
2082
-
2083
- setDefaultAnimation('select.show', {
2084
- keyframes: [
2085
- {opacity: 0, scale: 0.9},
2086
- {opacity: 1, scale: 1}
2087
- ],
2088
- options: {duration: 100, easing: 'ease'}
2089
- });
2090
-
2091
- setDefaultAnimation('select.hide', {
2092
- keyframes: [
2093
- {opacity: 1, scale: 1},
2094
- {opacity: 0, scale: 0.9}
2095
- ],
2096
- options: {duration: 100, easing: 'ease'}
2097
- });
@@ -17,13 +17,7 @@
17
17
  z-index: var(--zn-z-index-dropdown);
18
18
  }
19
19
 
20
- .select[data-current-placement^='top']::part(popup) {
21
- transform-origin: bottom;
22
- }
23
-
24
- .select[data-current-placement^='bottom']::part(popup) {
25
- transform-origin: top;
26
- }
20
+ @include wc.popover-motion('.select');
27
21
 
28
22
  /* Combobox */
29
23
  .select__combobox {
@@ -63,6 +57,8 @@
63
57
  color: var(--zn-input-color);
64
58
  cursor: inherit;
65
59
  overflow: hidden;
60
+ text-overflow: ellipsis;
61
+ white-space: nowrap;
66
62
  padding: 0;
67
63
  margin: 0;
68
64
  -webkit-appearance: none;
@@ -123,17 +119,16 @@
123
119
  /* Ensure the combobox wraps so the input flows after tags (only when open to avoid affecting initial size) */
124
120
  .select--multiple.select--search.select--open .select__combobox {
125
121
  flex-wrap: wrap;
126
- gap: var(--zn-spacing-2x-small);
122
+ // Row gap only: column spacing comes from the items' own margins, as when closed.
123
+ row-gap: var(--zn-spacing-2x-small);
127
124
  padding-inline-start: 0;
128
- /* Allow the control to grow with the wrapped tag rows instead of clipping them, and pack the rows
129
- from the top with a little vertical padding. align-self stops the popup from stretching the
130
- combobox to a fixed height, so it sizes to its (wrapped) content. */
125
+ /* Grow with wrapped tag rows instead of clipping them. Rows stay centred and the size's closed
126
+ padding-block is kept, so a single row doesn't shift when the popup opens. */
131
127
  overflow: visible;
132
- align-content: flex-start;
128
+ align-content: center;
133
129
  align-items: center;
134
130
  align-self: flex-start;
135
131
  height: auto;
136
- padding-block: var(--zn-spacing-2x-small);
137
132
  }
138
133
 
139
134
  .select__value-input {
@@ -159,7 +154,14 @@
159
154
  /* The tags are rendered into the shadow (not slotted), so target them as descendants. Only the remove
160
155
  "X" is clickable (pointer); the chip body isn't, so give it a default cursor rather than letting it
161
156
  inherit the combobox's text cursor in search/free-text mode. */
157
+ // Flex, so the inline chip isn't seated on the line box's baseline.
158
+ .select__tags > div {
159
+ display: flex;
160
+ }
161
+
162
162
  .select__tags zn-chip {
163
+ --zn-chip-border-radius: var(--zn-select-tag-border-radius);
164
+ --zn-chip-height: var(--zn-select-tag-height);
163
165
  cursor: default;
164
166
  }
165
167
 
@@ -167,6 +169,11 @@
167
169
  cursor: pointer;
168
170
  }
169
171
 
172
+ .select__tags zn-icon[slot="action"]:focus-visible {
173
+ outline: var(--zn-focus-ring);
174
+ border-radius: var(--zn-border-radius-small);
175
+ }
176
+
170
177
  .select--disabled .select__tags,
171
178
  .select--disabled .select__tags zn-chip,
172
179
  .select--disabled .select__tags zn-icon[slot="action"] {
@@ -177,6 +184,17 @@
177
184
  .select--standard .select__combobox {
178
185
  background-color: var(--zn-input-background-color);
179
186
  border: solid var(--zn-input-border-width) var(--zn-input-border-color);
187
+ box-shadow: var(--zn-input-shadow, none);
188
+ }
189
+
190
+ /* Invalid, once the user has interacted */
191
+ :host([data-user-invalid]) .select--standard:not(.select--disabled) .select__combobox {
192
+ border-color: var(--zn-input-border-color-invalid);
193
+ }
194
+
195
+ :host([data-user-invalid]) .select--standard:not(.select--disabled).select--focused .select__combobox,
196
+ :host([data-user-invalid]) .select--standard:not(.select--disabled).select--open .select__combobox {
197
+ box-shadow: 0 0 0 var(--zn-focus-ring-width) var(--zn-input-focus-ring-color-invalid);
180
198
  }
181
199
 
182
200
  .select--standard.select--disabled .select__combobox {
@@ -206,7 +224,7 @@
206
224
  font-size: var(--zn-input-font-size-small);
207
225
  min-height: var(--zn-input-height-small);
208
226
  padding-block: 0;
209
- padding-inline: var(--zn-spacing-small);
227
+ padding-inline: var(--zn-input-padding-inline, var(--zn-spacing-small));
210
228
  }
211
229
 
212
230
  .select--small .select__clear {
@@ -231,7 +249,7 @@
231
249
  font-size: var(--zn-input-font-size-medium);
232
250
  min-height: var(--zn-input-height-medium);
233
251
  padding-block: 0;
234
- padding-inline: var(--zn-spacing-small);
252
+ padding-inline: var(--zn-input-padding-inline, var(--zn-spacing-small));
235
253
  }
236
254
 
237
255
  .select--has-input-prefix.select--medium .select__combobox {
@@ -260,7 +278,7 @@
260
278
  font-size: var(--zn-input-font-size-large);
261
279
  min-height: var(--zn-input-height-large);
262
280
  padding-block: 0;
263
- padding-inline: var(--zn-spacing-small);
281
+ padding-inline: var(--zn-input-padding-inline, var(--zn-spacing-small));
264
282
  }
265
283
 
266
284
  .select--has-input-prefix.select--large .select__combobox {
@@ -355,6 +373,10 @@
355
373
  outline: none;
356
374
  }
357
375
 
376
+ .select__clear:focus-visible {
377
+ outline: var(--zn-focus-ring);
378
+ }
379
+
358
380
  /* Expand icon */
359
381
  .select__expand-icon {
360
382
  flex: 0 0 auto;
@@ -362,11 +384,11 @@
362
384
  align-items: center;
363
385
  transition: var(--zn-transition-medium) rotate ease;
364
386
  rotate: 0;
365
- margin-inline-start: var(--zn-spacing-small);
387
+ margin-inline-start: var(--zn-select-expand-icon-spacing, var(--zn-spacing-small));
366
388
 
367
389
  zn-icon {
368
- --icon-size: var(--zn-font-size-large);
369
- --icon-color: var(--zn-input-icon-color);
390
+ --icon-size: var(--zn-select-expand-icon-size, var(--zn-font-size-large));
391
+ --icon-color: var(--zn-select-expand-icon-color, var(--zn-input-icon-color));
370
392
  }
371
393
  }
372
394
 
@@ -376,16 +398,11 @@
376
398
 
377
399
  /* Fetch loading spinner */
378
400
  .select__spinner {
379
- animation: spin 1s linear infinite;
401
+ @include wc.spin;
380
402
  --icon-size: var(--zn-font-size-large);
381
403
  --icon-color: var(--zn-input-icon-color);
382
404
  }
383
405
 
384
- @keyframes spin {
385
- from { rotate: 0deg; }
386
- to { rotate: 360deg; }
387
- }
388
-
389
406
  /* Fetch error icon */
390
407
  .select__fetch-error-icon {
391
408
  --icon-size: var(--zn-font-size-large);
@@ -233,7 +233,7 @@ describe('<zn-select>', () => {
233
233
  });
234
234
 
235
235
  describe('Escape key', () => {
236
- it('blurs the display input when dropdown is closed and Escape is pressed', async () => {
236
+ it('keeps focus on the display input when the dropdown is closed and Escape is pressed', async () => {
237
237
  const el = await fixture<ZnSelect>(html`<zn-select></zn-select>`);
238
238
  await el.updateComplete;
239
239
 
@@ -251,7 +251,7 @@ describe('<zn-select>', () => {
251
251
  }));
252
252
  await el.updateComplete;
253
253
 
254
- expect(el.shadowRoot!.activeElement, 'display input should be blurred').to.not.equal(displayInput);
254
+ expect(el.shadowRoot!.activeElement, 'display input should keep focus').to.equal(displayInput);
255
255
  });
256
256
 
257
257
  });
@@ -891,6 +891,18 @@ describe('<zn-select> disabled', () => {
891
891
  expect(el.open).to.be.false;
892
892
  });
893
893
 
894
+ it('should take its chevron from the theme', async () => {
895
+ const el: any = await fixture(html`
896
+ <zn-select style="--zn-select-expand-icon: 'expand_more'; --zn-select-expand-icon-size: 18">
897
+ <zn-option value="a">A</zn-option>
898
+ </zn-select>`);
899
+ await el.updateComplete;
900
+
901
+ const icon = el.shadowRoot.querySelector('.select__expand-icon zn-icon');
902
+ expect(icon.getAttribute('src')).to.equal('expand_more');
903
+ expect(icon.getAttribute('size')).to.equal('18');
904
+ });
905
+
894
906
  it('should open from the expand icon when enabled', async () => {
895
907
  const el: any = await fixture(html`
896
908
  <zn-select>
@@ -71,13 +71,26 @@
71
71
 
72
72
  .setting-container__toggle-button::part(icon) {
73
73
  rotate: 0deg;
74
- transition: rotate 0.9s ease-in-out, color 0.9s ease-in-out;
74
+ transition: rotate var(--zn-transition-medium) var(--zn-ease-out), color var(--zn-transition-fast) ease;
75
75
  }
76
76
 
77
- .setting-container__dropdown[open] .setting-container__toggle-button::part(icon), .setting-container__toggle-button:hover::part(icon) {
78
- color: rgb(var(--zn-primary));
79
- cursor: pointer;
80
- rotate: 380deg;
77
+ .setting-container__dropdown[open] .setting-container__toggle-button::part(icon) {
78
+ color: var(--zn-color-primary-fg, rgb(var(--zn-primary)));
79
+ rotate: 90deg;
80
+ }
81
+
82
+ @include wc.hover-fine {
83
+ .setting-container__toggle-button:hover::part(icon) {
84
+ color: var(--zn-color-primary-fg, rgb(var(--zn-primary)));
85
+ cursor: pointer;
86
+ rotate: 90deg;
87
+ }
88
+ }
89
+
90
+ @include wc.reduced-motion {
91
+ .setting-container__toggle-button::part(icon) {
92
+ transition: color var(--zn-transition-fast) ease;
93
+ }
81
94
  }
82
95
 
83
96
  zn-button {
@@ -83,7 +83,14 @@ export default class ZnSidebar extends ZincElement {
83
83
  _expander() {
84
84
  const smpCap = this.caption ?? "Close";
85
85
  return html`
86
- <div id="expander" @click="${(e: MouseEvent) => this.handleClick(e)}">
86
+ <div id="expander" role="button" tabindex="0" aria-expanded="${this.open}"
87
+ @click="${(e: MouseEvent) => this.handleClick(e)}"
88
+ @keydown="${(e: KeyboardEvent) => {
89
+ if (e.key === 'Enter' || e.key === ' ') {
90
+ e.preventDefault();
91
+ this.handleClick(e);
92
+ }
93
+ }}">
87
94
  <zn-icon src="arrow_downward" library="material"></zn-icon>
88
95
  <span class="close"> Close ${this.caption}</span>
89
96
  <span class="close-sm">${smpCap}</span>
@@ -107,6 +107,11 @@
107
107
  }
108
108
 
109
109
  #expander {
110
+ &:focus-visible {
111
+ outline: var(--zn-focus-ring);
112
+ outline-offset: calc(-1 * var(--zn-focus-ring-width));
113
+ }
114
+
110
115
  cursor: pointer;
111
116
  display: flex;
112
117
  flex-direction: row-reverse;
@@ -162,7 +167,7 @@
162
167
  color: rgb(var(--zn-text));
163
168
  margin-left: var(--zn-spacing-medium);
164
169
  margin-right: var(--zn-spacing-medium);
165
- transition: all 500ms ease-in-out;
170
+ transition: rotate var(--zn-transition-medium) var(--zn-ease-out);
166
171
  rotate: 0;
167
172
 
168
173
  @include wc.container-query(ph) {
@@ -15,7 +15,7 @@ import styles from './skeleton.scss';
15
15
  * @property {string} speed - Animation speed for the shimmer effect. Default: "3s"
16
16
  * @property {string} width - Width of the skeleton element. Default: "100%"
17
17
  * @property {string} height - Height of the skeleton element. Default: "20px"
18
- * @property {string} radius - Border radius of the skeleton element. Default: "4px"
18
+ * @property {string} radius - Border radius of the skeleton element. Defaults to the theme's `--zn-skeleton-border-radius` (4px).
19
19
  */
20
20
  export default class ZnSkeleton extends ZincElement {
21
21
  static styles: CSSResultGroup = unsafeCSS(styles);
@@ -23,7 +23,7 @@ export default class ZnSkeleton extends ZincElement {
23
23
  @property({attribute: 'speed', type: String}) speed = '3s';
24
24
  @property({attribute: 'width', type: String}) width = '100%';
25
25
  @property({attribute: 'height', type: String}) height = '20px';
26
- @property({attribute: 'radius', type: String}) radius = '4px';
26
+ @property({attribute: 'radius', type: String}) radius = '';
27
27
 
28
28
  protected render(): unknown {
29
29
  return html`
@@ -32,7 +32,7 @@ export default class ZnSkeleton extends ZincElement {
32
32
  '--skeleton-speed': `${this.speed}`,
33
33
  '--skeleton-width': `${this.width}`,
34
34
  '--skeleton-height': `${this.height}`,
35
- '--skeleton-border-radius': `${this.radius}`,
35
+ ...(this.radius ? {'--skeleton-border-radius': this.radius} : {}),
36
36
  })}
37
37
  ></div>`;
38
38
  }