@boostdev/design-system-components 2.8.0 → 2.11.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 (534) hide show
  1. package/AGENTS.md +54 -46
  2. package/README.md +34 -20
  3. package/dist/client.cjs +1317 -779
  4. package/dist/client.css +1029 -812
  5. package/dist/client.d.cts +88 -26
  6. package/dist/client.d.ts +88 -26
  7. package/dist/client.js +1278 -732
  8. package/dist/index.cjs +1317 -779
  9. package/dist/index.css +1029 -812
  10. package/dist/index.d.cts +88 -26
  11. package/dist/index.d.ts +88 -26
  12. package/dist/index.js +1278 -732
  13. package/dist/web-components/chunk-2OLVQUBU.js +193 -0
  14. package/dist/web-components/{chunk-OF6FFGOT.js → chunk-3AY2YKCM.js} +77 -21
  15. package/dist/web-components/chunk-3WAV6MDN.js +212 -0
  16. package/dist/web-components/{chunk-UUKSDCYS.js → chunk-47AT5KZD.js} +87 -15
  17. package/dist/web-components/chunk-4A2YYTYN.js +93 -0
  18. package/dist/web-components/{chunk-Q4T5BJT6.js → chunk-62NK3ZSC.js} +18 -3
  19. package/dist/web-components/chunk-66M6ETWD.js +77 -0
  20. package/dist/web-components/{chunk-NCPQ7AF3.js → chunk-6G22I2CK.js} +18 -3
  21. package/dist/web-components/{chunk-QDST57JC.js → chunk-7ZOJ7N4E.js} +14 -4
  22. package/dist/web-components/{chunk-QLT6MTZF.js → chunk-AIBOHNDU.js} +10 -0
  23. package/dist/web-components/{chunk-X3NQMBAQ.js → chunk-AP4RDUL2.js} +14 -3
  24. package/dist/web-components/{chunk-QWPACK5L.js → chunk-BPYKZVDK.js} +11 -1
  25. package/dist/web-components/{chunk-YLVTEY23.js → chunk-BTCMJQKB.js} +53 -21
  26. package/dist/web-components/chunk-CUKQ2L5B.js +245 -0
  27. package/dist/web-components/chunk-DIZDCL7Z.js +14 -0
  28. package/dist/web-components/{chunk-PC3IOQAH.js → chunk-DV5T43ZC.js} +27 -7
  29. package/dist/web-components/{chunk-2QA62WCQ.js → chunk-EF7IVYTY.js} +10 -0
  30. package/dist/web-components/{chunk-L3XHOMN6.js → chunk-F3ZDNHZZ.js} +26 -1
  31. package/dist/web-components/chunk-FEDABOR5.js +248 -0
  32. package/dist/web-components/{chunk-6I2DBFQ7.js → chunk-HGFCJXOQ.js} +36 -5
  33. package/dist/web-components/{chunk-SOQQ7RVJ.js → chunk-IPGHUCJT.js} +23 -8
  34. package/dist/web-components/chunk-ITD2MV5K.js +392 -0
  35. package/dist/web-components/{chunk-ARMKC4BQ.js → chunk-JH6LQKLK.js} +77 -5
  36. package/dist/web-components/chunk-JMCXAAFK.js +120 -0
  37. package/dist/web-components/{chunk-KUI55GFB.js → chunk-JUPCZVVW.js} +50 -18
  38. package/dist/web-components/chunk-JV5QT2OU.js +146 -0
  39. package/dist/web-components/{chunk-3GFWLSLS.js → chunk-KA3VPKMY.js} +29 -6
  40. package/dist/web-components/{chunk-CR5PGUHV.js → chunk-KJGRFDFI.js} +26 -11
  41. package/dist/web-components/{chunk-PY62FTRW.js → chunk-KZPRFY5P.js} +68 -33
  42. package/dist/web-components/{chunk-X46KL5BK.js → chunk-LDIPCTRN.js} +18 -1
  43. package/dist/web-components/chunk-M3ECULRH.js +174 -0
  44. package/dist/web-components/chunk-NBN2ENWJ.js +90 -0
  45. package/dist/web-components/chunk-NIN3JO6Q.js +189 -0
  46. package/dist/web-components/{chunk-2FGATTGT.js → chunk-NTQ4TCUT.js} +76 -55
  47. package/dist/web-components/chunk-OY74D4X6.js +302 -0
  48. package/dist/web-components/{chunk-3S42DZ7W.js → chunk-P24JYC5V.js} +7 -0
  49. package/dist/web-components/{chunk-BKIHQYJR.js → chunk-PXPPKCLT.js} +17 -2
  50. package/dist/web-components/{chunk-TQ7IQ4GZ.js → chunk-QEF2IRID.js} +71 -29
  51. package/dist/web-components/chunk-QZAIRJ75.js +111 -0
  52. package/dist/web-components/{chunk-6I3CFC26.js → chunk-RSZ3BWBK.js} +20 -5
  53. package/dist/web-components/chunk-RVF7W653.js +101 -0
  54. package/dist/web-components/chunk-SEO2F5KJ.js +234 -0
  55. package/dist/web-components/{chunk-VMMVWLXL.js → chunk-SFZ6Q4BP.js} +10 -0
  56. package/dist/web-components/{chunk-LY62SAVN.js → chunk-SYNLFKD3.js} +12 -2
  57. package/dist/web-components/chunk-TMWXRHGF.js +192 -0
  58. package/dist/web-components/{chunk-65JXQOBA.js → chunk-U3YZE6R6.js} +51 -7
  59. package/dist/web-components/chunk-UO7ROSHD.js +424 -0
  60. package/dist/web-components/chunk-VANAKB6D.js +152 -0
  61. package/dist/web-components/{chunk-PXZWYO6Z.js → chunk-VED2DFJ6.js} +108 -29
  62. package/dist/web-components/chunk-W6H5ID2U.js +161 -0
  63. package/dist/web-components/{chunk-FSZRP43R.js → chunk-WFVKU4GX.js} +21 -10
  64. package/dist/web-components/{chunk-OQTRTMAB.js → chunk-WIBAN7KP.js} +10 -0
  65. package/dist/web-components/chunk-XI7KRAH7.js +54 -0
  66. package/dist/web-components/{chunk-ORC56MDY.js → chunk-XIZWAWMJ.js} +45 -6
  67. package/dist/web-components/{chunk-FXURM6D5.js → chunk-YFAXGRPR.js} +10 -0
  68. package/dist/web-components/globals.js +1 -1
  69. package/dist/web-components/index.d.ts +77 -707
  70. package/dist/web-components/index.js +339 -2066
  71. package/dist/web-components/interaction/bds-accordion-item.js +1 -1
  72. package/dist/web-components/interaction/bds-accordion.js +1 -1
  73. package/dist/web-components/interaction/bds-button.d.ts +10 -2
  74. package/dist/web-components/interaction/bds-button.js +1 -1
  75. package/dist/web-components/interaction/bds-collapsible.d.ts +7 -2
  76. package/dist/web-components/interaction/bds-collapsible.js +1 -1
  77. package/dist/web-components/interaction/bds-dialog.d.ts +11 -3
  78. package/dist/web-components/interaction/bds-dialog.js +1 -1
  79. package/dist/web-components/interaction/bds-drawer.d.ts +7 -1
  80. package/dist/web-components/interaction/bds-drawer.js +1 -1
  81. package/dist/web-components/interaction/bds-dropdown-menu-item.d.ts +51 -0
  82. package/dist/web-components/interaction/bds-dropdown-menu-item.js +7 -0
  83. package/dist/web-components/interaction/bds-dropdown-menu.d.ts +70 -0
  84. package/dist/web-components/interaction/bds-dropdown-menu.js +7 -0
  85. package/dist/web-components/interaction/bds-popover.d.ts +14 -3
  86. package/dist/web-components/interaction/bds-popover.js +1 -1
  87. package/dist/web-components/interaction/bds-skip-link.js +1 -1
  88. package/dist/web-components/interaction/bds-tab-panel.js +1 -1
  89. package/dist/web-components/interaction/bds-tab.js +1 -1
  90. package/dist/web-components/interaction/bds-tabs.d.ts +1 -0
  91. package/dist/web-components/interaction/bds-tabs.js +1 -1
  92. package/dist/web-components/interaction/bds-toast-provider.js +1 -1
  93. package/dist/web-components/interaction/bds-tooltip.d.ts +19 -3
  94. package/dist/web-components/interaction/bds-tooltip.js +1 -1
  95. package/dist/web-components/interaction/form/bds-checkbox-group.d.ts +83 -0
  96. package/dist/web-components/interaction/form/bds-checkbox-group.js +7 -0
  97. package/dist/web-components/interaction/form/bds-checkbox.d.ts +6 -0
  98. package/dist/web-components/interaction/form/bds-checkbox.js +1 -1
  99. package/dist/web-components/interaction/form/bds-combobox.d.ts +18 -0
  100. package/dist/web-components/interaction/form/bds-combobox.js +1 -1
  101. package/dist/web-components/interaction/form/bds-field-group.d.ts +89 -0
  102. package/dist/web-components/interaction/form/bds-field-group.js +7 -0
  103. package/dist/web-components/interaction/form/bds-file-input.d.ts +1 -1
  104. package/dist/web-components/interaction/form/bds-file-input.js +1 -1
  105. package/dist/web-components/interaction/form/bds-form-input.d.ts +92 -0
  106. package/dist/web-components/interaction/form/bds-form-input.js +7 -0
  107. package/dist/web-components/interaction/form/bds-number-input.d.ts +18 -1
  108. package/dist/web-components/interaction/form/bds-number-input.js +1 -1
  109. package/dist/web-components/interaction/form/bds-radio-group.d.ts +81 -0
  110. package/dist/web-components/interaction/form/bds-radio-group.js +7 -0
  111. package/dist/web-components/interaction/form/bds-radio.d.ts +34 -6
  112. package/dist/web-components/interaction/form/bds-radio.js +1 -1
  113. package/dist/web-components/interaction/form/bds-segmented-control.d.ts +4 -4
  114. package/dist/web-components/interaction/form/bds-segmented-control.js +1 -1
  115. package/dist/web-components/interaction/form/bds-select.d.ts +22 -1
  116. package/dist/web-components/interaction/form/bds-select.js +1 -1
  117. package/dist/web-components/interaction/form/bds-slider.d.ts +42 -10
  118. package/dist/web-components/interaction/form/bds-slider.js +1 -1
  119. package/dist/web-components/interaction/form/bds-switch.d.ts +20 -0
  120. package/dist/web-components/interaction/form/bds-switch.js +1 -1
  121. package/dist/web-components/interaction/form/bds-textarea.d.ts +23 -3
  122. package/dist/web-components/interaction/form/bds-textarea.js +1 -1
  123. package/dist/web-components/layout/bds-grid-item.d.ts +63 -0
  124. package/dist/web-components/layout/bds-grid-item.js +7 -0
  125. package/dist/web-components/layout/bds-grid.d.ts +108 -0
  126. package/dist/web-components/layout/bds-grid.js +7 -0
  127. package/dist/web-components/ui/bds-alert.d.ts +16 -2
  128. package/dist/web-components/ui/bds-alert.js +1 -1
  129. package/dist/web-components/ui/bds-avatar.d.ts +2 -1
  130. package/dist/web-components/ui/bds-avatar.js +1 -1
  131. package/dist/web-components/ui/bds-badge.js +1 -1
  132. package/dist/web-components/ui/bds-breadcrumb.d.ts +3 -1
  133. package/dist/web-components/ui/bds-breadcrumb.js +1 -1
  134. package/dist/web-components/ui/bds-button-container.d.ts +52 -0
  135. package/dist/web-components/ui/bds-button-container.js +7 -0
  136. package/dist/web-components/ui/bds-button-group.d.ts +21 -0
  137. package/dist/web-components/ui/bds-button-group.js +8 -0
  138. package/dist/web-components/ui/bds-calendar.d.ts +121 -0
  139. package/dist/web-components/ui/bds-calendar.js +7 -0
  140. package/dist/web-components/ui/bds-card.d.ts +12 -3
  141. package/dist/web-components/ui/bds-card.js +1 -1
  142. package/dist/web-components/ui/bds-carousel.d.ts +98 -0
  143. package/dist/web-components/ui/bds-carousel.js +7 -0
  144. package/dist/web-components/ui/bds-description-list.js +1 -1
  145. package/dist/web-components/ui/bds-icon-wrapper.d.ts +0 -9
  146. package/dist/web-components/ui/bds-icon-wrapper.js +1 -1
  147. package/dist/web-components/ui/bds-link.js +1 -1
  148. package/dist/web-components/ui/bds-loading.js +1 -1
  149. package/dist/web-components/ui/bds-notification-banner.js +1 -1
  150. package/dist/web-components/ui/bds-pagination.d.ts +47 -0
  151. package/dist/web-components/ui/bds-pagination.js +7 -0
  152. package/dist/web-components/ui/bds-progress-circle.d.ts +3 -1
  153. package/dist/web-components/ui/bds-progress-circle.js +1 -1
  154. package/dist/web-components/ui/bds-progress.d.ts +3 -1
  155. package/dist/web-components/ui/bds-progress.js +1 -1
  156. package/dist/web-components/ui/bds-rating.js +1 -1
  157. package/dist/web-components/ui/bds-section-header.d.ts +18 -4
  158. package/dist/web-components/ui/bds-section-header.js +1 -1
  159. package/dist/web-components/ui/bds-separator.js +1 -1
  160. package/dist/web-components/ui/bds-skeleton.js +1 -1
  161. package/dist/web-components/ui/bds-table.d.ts +52 -0
  162. package/dist/web-components/ui/bds-table.js +7 -0
  163. package/dist/web-components/ui/bds-typography.d.ts +1 -0
  164. package/dist/web-components/ui/bds-typography.js +1 -1
  165. package/package.json +60 -3
  166. package/src/components/interaction/Button/Button.module.css +23 -14
  167. package/src/components/interaction/Button/Button.spec.tsx +20 -0
  168. package/src/components/interaction/Button/Button.tsx +2 -2
  169. package/src/components/interaction/Command/Command.mdx +5 -2
  170. package/src/components/interaction/Command/Command.module.css +23 -7
  171. package/src/components/interaction/Command/Command.spec.tsx +35 -0
  172. package/src/components/interaction/Command/Command.tsx +15 -4
  173. package/src/components/interaction/Command/index.ts +1 -1
  174. package/src/components/interaction/Dialog/Dialog.mdx +4 -4
  175. package/src/components/interaction/Dialog/Dialog.module.css +20 -0
  176. package/src/components/interaction/Dialog/Dialog.spec.tsx +20 -0
  177. package/src/components/interaction/Dialog/Dialog.tsx +8 -3
  178. package/src/components/interaction/Dialog/index.ts +1 -0
  179. package/src/components/interaction/Drawer/Drawer.mdx +5 -2
  180. package/src/components/interaction/Drawer/Drawer.module.css +34 -3
  181. package/src/components/interaction/Drawer/Drawer.spec.tsx +67 -1
  182. package/src/components/interaction/Drawer/Drawer.tsx +30 -12
  183. package/src/components/interaction/Drawer/index.ts +1 -0
  184. package/src/components/interaction/DropdownMenu/DropdownMenu.mdx +2 -0
  185. package/src/components/interaction/DropdownMenu/DropdownMenu.spec.tsx +34 -0
  186. package/src/components/interaction/DropdownMenu/DropdownMenu.tsx +15 -5
  187. package/src/components/interaction/DropdownMenu/index.ts +1 -0
  188. package/src/components/interaction/Popover/Popover.mdx +6 -2
  189. package/src/components/interaction/Popover/Popover.module.css +26 -18
  190. package/src/components/interaction/Popover/Popover.spec.tsx +38 -0
  191. package/src/components/interaction/Popover/Popover.tsx +19 -5
  192. package/src/components/interaction/Popover/index.ts +1 -0
  193. package/src/components/interaction/Rating/Rating.mdx +1 -1
  194. package/src/components/interaction/Rating/Rating.module.css +2 -2
  195. package/src/components/interaction/Rating/Rating.tsx +1 -1
  196. package/src/components/interaction/Rating/index.ts +1 -0
  197. package/src/components/interaction/Toast/Toast.mdx +3 -0
  198. package/src/components/interaction/Toast/Toast.module.css +35 -5
  199. package/src/components/interaction/Toast/Toast.spec.tsx +69 -1
  200. package/src/components/interaction/Toast/Toast.tsx +15 -9
  201. package/src/components/interaction/form/Checkbox/Checkbox.mdx +3 -0
  202. package/src/components/interaction/form/Checkbox/Checkbox.module.css +13 -6
  203. package/src/components/interaction/form/Checkbox/Checkbox.spec.tsx +6 -0
  204. package/src/components/interaction/form/Checkbox/Checkbox.tsx +1 -1
  205. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.mdx +16 -1
  206. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.module.css +24 -8
  207. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.spec.tsx +32 -2
  208. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.tsx +14 -2
  209. package/src/components/interaction/form/Combobox/Combobox.mdx +11 -4
  210. package/src/components/interaction/form/Combobox/Combobox.module.css +6 -6
  211. package/src/components/interaction/form/Combobox/Combobox.spec.tsx +47 -0
  212. package/src/components/interaction/form/Combobox/Combobox.tsx +10 -5
  213. package/src/components/interaction/form/FieldGroup/FieldGroup.mdx +9 -10
  214. package/src/components/interaction/form/FieldGroup/FieldGroup.module.css +57 -23
  215. package/src/components/interaction/form/FieldGroup/FieldGroup.spec.tsx +129 -7
  216. package/src/components/interaction/form/FieldGroup/FieldGroup.tsx +72 -12
  217. package/src/components/interaction/form/FileInput/FileInput.mdx +9 -1
  218. package/src/components/interaction/form/FileInput/FileInput.module.css +8 -8
  219. package/src/components/interaction/form/FileInput/FileInput.spec.tsx +89 -1
  220. package/src/components/interaction/form/FileInput/FileInput.tsx +6 -2
  221. package/src/components/interaction/form/FormInput/FormInput.mdx +9 -5
  222. package/src/components/interaction/form/FormInput/FormInput.module.css +17 -8
  223. package/src/components/interaction/form/FormInput/FormInput.spec.tsx +20 -0
  224. package/src/components/interaction/form/FormInput/FormInput.tsx +7 -2
  225. package/src/components/interaction/form/NumberInput/NumberInput.mdx +5 -1
  226. package/src/components/interaction/form/NumberInput/NumberInput.module.css +6 -6
  227. package/src/components/interaction/form/NumberInput/NumberInput.spec.tsx +51 -0
  228. package/src/components/interaction/form/NumberInput/NumberInput.tsx +36 -8
  229. package/src/components/interaction/form/Radio/Radio.mdx +8 -1
  230. package/src/components/interaction/form/Radio/Radio.module.css +20 -7
  231. package/src/components/interaction/form/Radio/Radio.spec.tsx +15 -0
  232. package/src/components/interaction/form/Radio/Radio.tsx +10 -4
  233. package/src/components/interaction/form/RadioGroup/RadioGroup.mdx +16 -1
  234. package/src/components/interaction/form/RadioGroup/RadioGroup.module.css +24 -8
  235. package/src/components/interaction/form/RadioGroup/RadioGroup.spec.tsx +32 -2
  236. package/src/components/interaction/form/RadioGroup/RadioGroup.tsx +14 -2
  237. package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +9 -3
  238. package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +25 -12
  239. package/src/components/interaction/form/SegmentedControl/SegmentedControl.spec.tsx +86 -5
  240. package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +44 -4
  241. package/src/components/interaction/form/Select/Select.mdx +10 -4
  242. package/src/components/interaction/form/Select/Select.module.css +4 -4
  243. package/src/components/interaction/form/Select/Select.spec.tsx +34 -0
  244. package/src/components/interaction/form/Select/Select.tsx +21 -9
  245. package/src/components/interaction/form/Slider/Slider.mdx +4 -1
  246. package/src/components/interaction/form/Slider/Slider.module.css +32 -8
  247. package/src/components/interaction/form/Slider/Slider.spec.tsx +29 -0
  248. package/src/components/interaction/form/Slider/Slider.tsx +9 -7
  249. package/src/components/interaction/form/Switch/Switch.mdx +2 -2
  250. package/src/components/interaction/form/Switch/Switch.module.css +12 -13
  251. package/src/components/interaction/form/Switch/Switch.spec.tsx +20 -0
  252. package/src/components/interaction/form/Switch/Switch.tsx +2 -1
  253. package/src/components/interaction/form/Textarea/Textarea.mdx +5 -0
  254. package/src/components/interaction/form/Textarea/Textarea.module.css +5 -5
  255. package/src/components/interaction/form/Textarea/Textarea.spec.tsx +13 -0
  256. package/src/components/interaction/form/Textarea/Textarea.tsx +3 -1
  257. package/src/components/interaction/form/atoms/Message.module.css +1 -1
  258. package/src/components/interaction/form/atoms/Message.spec.tsx +29 -0
  259. package/src/components/interaction/form/atoms/Message.tsx +1 -1
  260. package/src/components/layout/ButtonGroup/ButtonGroup.mdx +11 -0
  261. package/src/components/layout/ButtonGroup/ButtonGroup.module.css +1 -5
  262. package/src/components/layout/ButtonGroup/ButtonGroup.stories.tsx +14 -0
  263. package/src/components/layout/Card/Card.mdx +6 -1
  264. package/src/components/layout/Card/Card.module.css +26 -5
  265. package/src/components/layout/Card/Card.spec.tsx +7 -0
  266. package/src/components/layout/Card/Card.tsx +4 -3
  267. package/src/components/layout/Grid/Grid.spec.tsx +44 -0
  268. package/src/components/layout/Grid/Grid.tsx +5 -5
  269. package/src/components/layout/Grid/GridItem.tsx +6 -6
  270. package/src/components/layout/Grid/masonry.ts +31 -5
  271. package/src/components/layout/Grid/useIsomorphicLayoutEffect.ts +11 -0
  272. package/src/components/layout/IconWrapper/IconWrapper.mdx +8 -2
  273. package/src/components/layout/IconWrapper/IconWrapper.module.css +9 -6
  274. package/src/components/layout/SectionHeader/SectionHeader.mdx +4 -1
  275. package/src/components/layout/SectionHeader/SectionHeader.module.css +10 -9
  276. package/src/components/ui/Accordion/Accordion.mdx +4 -1
  277. package/src/components/ui/Accordion/Accordion.module.css +2 -1
  278. package/src/components/ui/Alert/Alert.mdx +21 -4
  279. package/src/components/ui/Alert/Alert.module.css +9 -4
  280. package/src/components/ui/Alert/Alert.spec.tsx +20 -0
  281. package/src/components/ui/Avatar/Avatar.mdx +8 -3
  282. package/src/components/ui/Avatar/Avatar.module.css +13 -8
  283. package/src/components/ui/Badge/Badge.mdx +3 -1
  284. package/src/components/ui/Breadcrumb/Breadcrumb.mdx +3 -0
  285. package/src/components/ui/Breadcrumb/Breadcrumb.module.css +4 -0
  286. package/src/components/ui/Breadcrumb/Breadcrumb.spec.tsx +12 -0
  287. package/src/components/ui/Breadcrumb/Breadcrumb.tsx +11 -3
  288. package/src/components/ui/Calendar/Calendar.mdx +6 -0
  289. package/src/components/ui/Calendar/Calendar.module.css +68 -19
  290. package/src/components/ui/Calendar/Calendar.spec.tsx +139 -24
  291. package/src/components/ui/Calendar/Calendar.stories.tsx +14 -0
  292. package/src/components/ui/Calendar/Calendar.tsx +143 -154
  293. package/src/components/ui/Calendar/CalendarRange.mdx +39 -0
  294. package/src/components/ui/Calendar/CalendarRange.spec.tsx +119 -0
  295. package/src/components/ui/Calendar/CalendarRange.stories.tsx +51 -0
  296. package/src/components/ui/Calendar/CalendarRange.tsx +213 -0
  297. package/src/components/ui/Calendar/MonthGrid.tsx +141 -0
  298. package/src/components/ui/Calendar/calendar-core.spec.ts +176 -0
  299. package/src/components/ui/Calendar/calendar-core.ts +164 -0
  300. package/src/components/ui/Calendar/index.ts +1 -0
  301. package/src/components/ui/Carousel/Carousel.mdx +8 -3
  302. package/src/components/ui/Carousel/Carousel.module.css +7 -5
  303. package/src/components/ui/Carousel/Carousel.spec.tsx +67 -0
  304. package/src/components/ui/Carousel/Carousel.tsx +19 -7
  305. package/src/components/ui/Collapsible/Collapsible.mdx +17 -6
  306. package/src/components/ui/Collapsible/Collapsible.module.css +7 -2
  307. package/src/components/ui/Collapsible/Collapsible.spec.tsx +40 -0
  308. package/src/components/ui/Collapsible/Collapsible.tsx +19 -2
  309. package/src/components/ui/DescriptionList/DescriptionList.mdx +2 -0
  310. package/src/components/ui/Link/Link.mdx +4 -2
  311. package/src/components/ui/Loading/Loading.mdx +6 -3
  312. package/src/components/ui/Loading/Loading.module.css +7 -7
  313. package/src/components/ui/Loading/Loading.spec.tsx +12 -0
  314. package/src/components/ui/Loading/Loading.tsx +8 -3
  315. package/src/components/ui/NotificationBanner/NotificationBanner.mdx +4 -0
  316. package/src/components/ui/NotificationBanner/NotificationBanner.module.css +5 -0
  317. package/src/components/ui/NotificationBanner/NotificationBanner.spec.tsx +20 -0
  318. package/src/components/ui/Pagination/Pagination.mdx +29 -7
  319. package/src/components/ui/Pagination/Pagination.module.css +15 -14
  320. package/src/components/ui/Progress/Progress.mdx +6 -2
  321. package/src/components/ui/Progress/Progress.module.css +1 -1
  322. package/src/components/ui/Progress/Progress.spec.tsx +17 -0
  323. package/src/components/ui/Progress/Progress.tsx +2 -2
  324. package/src/components/ui/ProgressCircle/ProgressCircle.mdx +8 -4
  325. package/src/components/ui/ProgressCircle/ProgressCircle.module.css +2 -2
  326. package/src/components/ui/ProgressCircle/ProgressCircle.spec.tsx +11 -1
  327. package/src/components/ui/ProgressCircle/ProgressCircle.tsx +1 -1
  328. package/src/components/ui/Separator/Separator.mdx +7 -0
  329. package/src/components/ui/Separator/Separator.module.css +1 -0
  330. package/src/components/ui/Skeleton/Skeleton.mdx +17 -0
  331. package/src/components/ui/Skeleton/Skeleton.module.css +12 -5
  332. package/src/components/ui/SkipLink/SkipLink.mdx +19 -0
  333. package/src/components/ui/SkipLink/SkipLink.module.css +8 -7
  334. package/src/components/ui/SkipLink/SkipLink.spec.tsx +28 -0
  335. package/src/components/ui/Table/Table.mdx +14 -0
  336. package/src/components/ui/Table/Table.module.css +13 -8
  337. package/src/components/ui/Table/Table.spec.tsx +56 -0
  338. package/src/components/ui/Table/Table.tsx +44 -6
  339. package/src/components/ui/Tabs/Tabs.mdx +16 -0
  340. package/src/components/ui/Tabs/Tabs.module.css +3 -3
  341. package/src/components/ui/Tabs/Tabs.spec.tsx +20 -0
  342. package/src/components/ui/Tabs/Tabs.tsx +5 -1
  343. package/src/components/ui/Tooltip/Tooltip.mdx +9 -0
  344. package/src/components/ui/Tooltip/Tooltip.module.css +32 -12
  345. package/src/components/ui/Tooltip/Tooltip.spec.tsx +56 -0
  346. package/src/components/ui/Tooltip/Tooltip.tsx +26 -7
  347. package/src/components/ui/Typography/Typography.mdx +7 -0
  348. package/src/components/ui/Typography/Typography.module.css +5 -5
  349. package/src/index.ts +7 -3
  350. package/src/stories/DesignSystem/Borders.mdx +14 -9
  351. package/src/stories/DesignSystem/Colors.mdx +43 -41
  352. package/src/stories/DesignSystem/Overview.mdx +4 -3
  353. package/src/stories/Introduction.mdx +5 -5
  354. package/src/web-components/globals.ts +7 -0
  355. package/src/web-components/index.ts +2 -0
  356. package/src/web-components/interaction/BdsAccordion.mdx +10 -1
  357. package/src/web-components/interaction/BdsButton.mdx +15 -4
  358. package/src/web-components/interaction/BdsButton.stories.tsx +1 -1
  359. package/src/web-components/interaction/BdsCollapsible.mdx +3 -3
  360. package/src/web-components/interaction/BdsDialog.mdx +12 -7
  361. package/src/web-components/interaction/BdsDialog.stories.tsx +2 -2
  362. package/src/web-components/interaction/BdsDrawer.mdx +9 -6
  363. package/src/web-components/interaction/BdsDropdownMenu.mdx +20 -1
  364. package/src/web-components/interaction/BdsPopover.mdx +7 -3
  365. package/src/web-components/interaction/BdsSkipLink.mdx +14 -1
  366. package/src/web-components/interaction/BdsTabs.mdx +18 -1
  367. package/src/web-components/interaction/BdsToastProvider.mdx +21 -3
  368. package/src/web-components/interaction/BdsTooltip.mdx +4 -4
  369. package/src/web-components/interaction/bds-accordion-item.ts +10 -0
  370. package/src/web-components/interaction/bds-accordion.spec.ts +41 -0
  371. package/src/web-components/interaction/bds-accordion.ts +28 -2
  372. package/src/web-components/interaction/bds-button.spec.ts +81 -0
  373. package/src/web-components/interaction/bds-button.ts +55 -8
  374. package/src/web-components/interaction/bds-collapsible.spec.ts +93 -2
  375. package/src/web-components/interaction/bds-collapsible.ts +49 -7
  376. package/src/web-components/interaction/bds-dialog.spec.ts +49 -0
  377. package/src/web-components/interaction/bds-dialog.ts +68 -11
  378. package/src/web-components/interaction/bds-drawer.spec.ts +93 -4
  379. package/src/web-components/interaction/bds-drawer.ts +54 -21
  380. package/src/web-components/interaction/bds-dropdown-menu-item.ts +12 -1
  381. package/src/web-components/interaction/bds-dropdown-menu.spec.ts +63 -0
  382. package/src/web-components/interaction/bds-dropdown-menu.ts +45 -7
  383. package/src/web-components/interaction/bds-popover.spec.ts +80 -6
  384. package/src/web-components/interaction/bds-popover.ts +83 -32
  385. package/src/web-components/interaction/bds-skip-link.spec.ts +18 -0
  386. package/src/web-components/interaction/bds-skip-link.ts +29 -8
  387. package/src/web-components/interaction/bds-tab-panel.ts +10 -0
  388. package/src/web-components/interaction/bds-tab.spec.ts +25 -0
  389. package/src/web-components/interaction/bds-tab.ts +20 -5
  390. package/src/web-components/interaction/bds-tabs.spec.ts +92 -5
  391. package/src/web-components/interaction/bds-tabs.ts +42 -1
  392. package/src/web-components/interaction/bds-toast-provider.spec.ts +43 -0
  393. package/src/web-components/interaction/bds-toast-provider.ts +50 -21
  394. package/src/web-components/interaction/bds-tooltip.spec.ts +71 -0
  395. package/src/web-components/interaction/bds-tooltip.ts +100 -5
  396. package/src/web-components/interaction/form/BdsCheckbox.mdx +20 -1
  397. package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +8 -0
  398. package/src/web-components/interaction/form/BdsCheckboxGroup.mdx +4 -3
  399. package/src/web-components/interaction/form/BdsCombobox.mdx +39 -2
  400. package/src/web-components/interaction/form/BdsCombobox.stories.tsx +31 -0
  401. package/src/web-components/interaction/form/BdsFieldGroup.mdx +8 -3
  402. package/src/web-components/interaction/form/BdsFieldGroup.stories.tsx +1 -1
  403. package/src/web-components/interaction/form/BdsFileInput.mdx +26 -5
  404. package/src/web-components/interaction/form/BdsFormInput.mdx +16 -1
  405. package/src/web-components/interaction/form/BdsNumberInput.mdx +34 -2
  406. package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +27 -3
  407. package/src/web-components/interaction/form/BdsRadio.mdx +39 -12
  408. package/src/web-components/interaction/form/BdsRadio.stories.tsx +26 -0
  409. package/src/web-components/interaction/form/BdsRadioGroup.mdx +9 -4
  410. package/src/web-components/interaction/form/BdsSegmentedControl.mdx +37 -11
  411. package/src/web-components/interaction/form/BdsSelect.mdx +22 -4
  412. package/src/web-components/interaction/form/BdsSelect.stories.tsx +33 -0
  413. package/src/web-components/interaction/form/BdsSlider.mdx +36 -19
  414. package/src/web-components/interaction/form/BdsSlider.stories.tsx +24 -0
  415. package/src/web-components/interaction/form/BdsSwitch.mdx +38 -11
  416. package/src/web-components/interaction/form/BdsSwitch.stories.tsx +16 -0
  417. package/src/web-components/interaction/form/BdsTextarea.mdx +42 -16
  418. package/src/web-components/interaction/form/BdsTextarea.stories.tsx +21 -0
  419. package/src/web-components/interaction/form/bds-checkbox-group.spec.ts +99 -0
  420. package/src/web-components/interaction/form/bds-checkbox-group.ts +95 -9
  421. package/src/web-components/interaction/form/bds-checkbox.spec.ts +55 -0
  422. package/src/web-components/interaction/form/bds-checkbox.ts +30 -5
  423. package/src/web-components/interaction/form/bds-combobox.spec.ts +79 -0
  424. package/src/web-components/interaction/form/bds-combobox.ts +101 -16
  425. package/src/web-components/interaction/form/bds-field-group.spec.ts +158 -0
  426. package/src/web-components/interaction/form/bds-field-group.ts +167 -23
  427. package/src/web-components/interaction/form/bds-file-input.spec.ts +73 -5
  428. package/src/web-components/interaction/form/bds-file-input.ts +71 -34
  429. package/src/web-components/interaction/form/bds-form-input.spec.ts +22 -0
  430. package/src/web-components/interaction/form/bds-form-input.ts +27 -16
  431. package/src/web-components/interaction/form/bds-number-input.spec.ts +49 -0
  432. package/src/web-components/interaction/form/bds-number-input.ts +118 -29
  433. package/src/web-components/interaction/form/bds-radio-group.spec.ts +57 -0
  434. package/src/web-components/interaction/form/bds-radio-group.ts +60 -12
  435. package/src/web-components/interaction/form/bds-radio.spec.ts +123 -0
  436. package/src/web-components/interaction/form/bds-radio.ts +135 -22
  437. package/src/web-components/interaction/form/bds-segmented-control.spec.ts +55 -0
  438. package/src/web-components/interaction/form/bds-segmented-control.ts +81 -59
  439. package/src/web-components/interaction/form/bds-select.spec.ts +57 -0
  440. package/src/web-components/interaction/form/bds-select.ts +95 -7
  441. package/src/web-components/interaction/form/bds-slider.spec.ts +83 -0
  442. package/src/web-components/interaction/form/bds-slider.ts +154 -26
  443. package/src/web-components/interaction/form/bds-switch.spec.ts +68 -0
  444. package/src/web-components/interaction/form/bds-switch.ts +87 -20
  445. package/src/web-components/interaction/form/bds-textarea.spec.ts +71 -0
  446. package/src/web-components/interaction/form/bds-textarea.ts +108 -7
  447. package/src/web-components/layout/BdsGrid.mdx +6 -2
  448. package/src/web-components/layout/BdsGrid.stories.tsx +4 -0
  449. package/src/web-components/layout/bds-grid-item.spec.ts +21 -0
  450. package/src/web-components/layout/bds-grid-item.ts +17 -3
  451. package/src/web-components/layout/bds-grid.spec.ts +98 -0
  452. package/src/web-components/layout/bds-grid.ts +139 -19
  453. package/src/web-components/ui/BdsAlert.mdx +6 -5
  454. package/src/web-components/ui/BdsAlert.stories.tsx +6 -6
  455. package/src/web-components/ui/BdsAvatar.mdx +4 -2
  456. package/src/web-components/ui/BdsBreadcrumb.mdx +3 -2
  457. package/src/web-components/ui/BdsButtonContainer.mdx +64 -0
  458. package/src/web-components/ui/BdsButtonContainer.stories.tsx +84 -0
  459. package/src/web-components/ui/BdsCalendar.mdx +29 -4
  460. package/src/web-components/ui/BdsCalendar.stories.tsx +16 -18
  461. package/src/web-components/ui/BdsCalendarRange.mdx +71 -0
  462. package/src/web-components/ui/BdsCalendarRange.stories.tsx +31 -0
  463. package/src/web-components/ui/BdsCard.mdx +7 -3
  464. package/src/web-components/ui/BdsCard.stories.tsx +17 -1
  465. package/src/web-components/ui/BdsCarousel.mdx +40 -12
  466. package/src/web-components/ui/BdsDescriptionList.mdx +6 -1
  467. package/src/web-components/ui/BdsIconWrapper.mdx +3 -2
  468. package/src/web-components/ui/BdsLink.mdx +14 -2
  469. package/src/web-components/ui/BdsNotificationBanner.mdx +18 -0
  470. package/src/web-components/ui/BdsPagination.mdx +40 -1
  471. package/src/web-components/ui/BdsProgress.mdx +8 -2
  472. package/src/web-components/ui/BdsProgressCircle.mdx +5 -2
  473. package/src/web-components/ui/BdsRating.mdx +7 -0
  474. package/src/web-components/ui/BdsSectionHeader.mdx +22 -3
  475. package/src/web-components/ui/BdsSectionHeader.stories.tsx +15 -13
  476. package/src/web-components/ui/BdsTable.mdx +23 -2
  477. package/src/web-components/ui/BdsTable.stories.tsx +8 -2
  478. package/src/web-components/ui/BdsTypography.mdx +17 -1
  479. package/src/web-components/ui/bds-alert.spec.ts +17 -2
  480. package/src/web-components/ui/bds-alert.ts +31 -5
  481. package/src/web-components/ui/bds-avatar.spec.ts +29 -0
  482. package/src/web-components/ui/bds-avatar.ts +29 -11
  483. package/src/web-components/ui/bds-badge.spec.ts +5 -0
  484. package/src/web-components/ui/bds-badge.ts +11 -1
  485. package/src/web-components/ui/bds-breadcrumb.spec.ts +30 -0
  486. package/src/web-components/ui/bds-breadcrumb.ts +26 -4
  487. package/src/web-components/ui/bds-button-container.spec.ts +39 -0
  488. package/src/web-components/ui/bds-button-container.ts +123 -0
  489. package/src/web-components/ui/bds-button-group.spec.ts +14 -20
  490. package/src/web-components/ui/bds-button-group.ts +13 -64
  491. package/src/web-components/ui/bds-calendar-range.spec.ts +123 -0
  492. package/src/web-components/ui/bds-calendar-range.ts +307 -0
  493. package/src/web-components/ui/bds-calendar.spec.ts +176 -0
  494. package/src/web-components/ui/bds-calendar.ts +186 -344
  495. package/src/web-components/ui/bds-card.spec.ts +32 -0
  496. package/src/web-components/ui/bds-card.ts +34 -9
  497. package/src/web-components/ui/bds-carousel.spec.ts +147 -0
  498. package/src/web-components/ui/bds-carousel.ts +109 -32
  499. package/src/web-components/ui/bds-description-list.spec.ts +15 -0
  500. package/src/web-components/ui/bds-description-list.ts +37 -3
  501. package/src/web-components/ui/bds-icon-wrapper.spec.ts +12 -0
  502. package/src/web-components/ui/bds-icon-wrapper.ts +15 -14
  503. package/src/web-components/ui/bds-link.spec.ts +17 -0
  504. package/src/web-components/ui/bds-link.ts +26 -11
  505. package/src/web-components/ui/bds-loading.ts +10 -0
  506. package/src/web-components/ui/bds-notification-banner.spec.ts +13 -0
  507. package/src/web-components/ui/bds-notification-banner.ts +18 -1
  508. package/src/web-components/ui/bds-pagination.spec.ts +44 -0
  509. package/src/web-components/ui/bds-pagination.ts +39 -19
  510. package/src/web-components/ui/bds-progress-circle.spec.ts +21 -0
  511. package/src/web-components/ui/bds-progress-circle.ts +17 -5
  512. package/src/web-components/ui/bds-progress.spec.ts +21 -0
  513. package/src/web-components/ui/bds-progress.ts +17 -4
  514. package/src/web-components/ui/bds-rating.spec.ts +6 -0
  515. package/src/web-components/ui/bds-rating.ts +12 -2
  516. package/src/web-components/ui/bds-section-header.spec.ts +39 -8
  517. package/src/web-components/ui/bds-section-header.ts +47 -13
  518. package/src/web-components/ui/bds-separator.ts +10 -0
  519. package/src/web-components/ui/bds-skeleton.ts +10 -0
  520. package/src/web-components/ui/bds-table.spec.ts +63 -0
  521. package/src/web-components/ui/bds-table.ts +88 -28
  522. package/src/web-components/ui/bds-typography.spec.ts +47 -0
  523. package/src/web-components/ui/bds-typography.ts +28 -10
  524. package/src/web-components/ui/calendar-styles.ts +94 -0
  525. package/dist/web-components/chunk-7YURXHTS.js +0 -147
  526. package/dist/web-components/chunk-A3RLT3AS.js +0 -49
  527. package/dist/web-components/chunk-AGKJTMJI.js +0 -56
  528. package/dist/web-components/chunk-BQLZ7I4G.js +0 -56
  529. package/dist/web-components/chunk-DZOEPVFT.js +0 -107
  530. package/dist/web-components/chunk-JYYRJS2D.js +0 -118
  531. package/dist/web-components/chunk-Y4MAXTMA.js +0 -80
  532. package/dist/web-components/chunk-Y7V7LM6R.js +0 -98
  533. package/src/web-components/ui/BdsButtonGroup.mdx +0 -69
  534. package/src/web-components/ui/BdsButtonGroup.stories.tsx +0 -66
@@ -1,4 +1,4 @@
1
- import { LitElement, css, html } from 'lit';
1
+ import { LitElement, css, html, nothing } from 'lit';
2
2
 
3
3
  export interface SelectOption {
4
4
  value: string;
@@ -17,15 +17,22 @@ export interface SelectOption {
17
17
  * value — currently selected value
18
18
  * options — JSON array of `{ value, label, disabled? }` option objects
19
19
  * placeholder — placeholder option label (disabled, empty value)
20
+ * label — visible label text (rendered as a shadow <label for>)
21
+ * hint — helper text shown below the select
22
+ * error — error message; when set the select enters error state
20
23
  * required — boolean
21
24
  * disabled — boolean
22
25
  *
26
+ * When `label` is not provided, a host `aria-label` attribute (if present) is
27
+ * forwarded to the inner `<select>` so the control always has an accessible name.
28
+ *
23
29
  * Events:
24
- * change — native change event (forwarded from inner select)
30
+ * bds-change — fired when the selected value changes; `detail: { value: string }`
25
31
  *
26
32
  * @example
27
33
  * <bds-select
28
34
  * name="country"
35
+ * label="Country"
29
36
  * placeholder="Choose…"
30
37
  * options='[{"value":"nl","label":"Netherlands"},{"value":"be","label":"Belgium"}]'
31
38
  * ></bds-select>
@@ -34,6 +41,16 @@ export class BdsSelect extends LitElement {
34
41
  static formAssociated = true;
35
42
 
36
43
  static styles = css`
44
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
45
+ here; otherwise elements with an explicit size + padding size as
46
+ content-box and layouts drift from the React (light-DOM) versions. */
47
+ :host,
48
+ *,
49
+ *::before,
50
+ *::after {
51
+ box-sizing: border-box;
52
+ }
53
+
37
54
  :host {
38
55
  display: block;
39
56
  }
@@ -43,6 +60,20 @@ export class BdsSelect extends LitElement {
43
60
  pointer-events: none;
44
61
  }
45
62
 
63
+ .label {
64
+ display: block;
65
+ font-size: var(--bds-font_size--body--s);
66
+ font-family: var(--bds-font_family--body);
67
+ font-weight: var(--bds-font_weight--semibold);
68
+ color: var(--bds-color_on-bg);
69
+ margin-block-end: var(--bds-space_xxs);
70
+ }
71
+
72
+ .required {
73
+ color: var(--bds-color_error);
74
+ margin-inline-start: var(--bds-space_xxxs);
75
+ }
76
+
46
77
  .wrapper {
47
78
  position: relative;
48
79
  display: block;
@@ -52,10 +83,10 @@ export class BdsSelect extends LitElement {
52
83
  inline-size: 100%;
53
84
  font-family: var(--bds-font_family--body);
54
85
  font-size: var(--bds-font_size--body);
55
- padding: var(--bds-space_s);
56
- padding-inline-end: var(--bds-space_xl);
57
- border: none;
58
- --bdc_color: var(--select_border-color, currentcolor);
86
+ padding: var(--select_padding, var(--bds-space_s));
87
+ padding-inline-end: var(--select_padding-end, var(--bds-space_xxl));
88
+ border: var(--select_border, none);
89
+ --bdc_color: currentcolor;
59
90
  --bdc-outline_radius: var(--bds-border_radius--full);
60
91
 
61
92
  border-radius: var(--select_radius, var(--bdc-outline_radius));
@@ -64,7 +95,8 @@ export class BdsSelect extends LitElement {
64
95
  color: var(--select_color, var(--bds-color_on-bg));
65
96
  appearance: none;
66
97
  cursor: pointer;
67
- transition: --bdc_color var(--bds-animation_transition-duration) var(--bds-animation_easing);
98
+ transition: --bdc_color var(--bds-animation_transition-duration) var(--bds-animation_easing),
99
+ background-color var(--bds-animation_transition-duration) var(--bds-animation_easing);
68
100
  }
69
101
 
70
102
  .select:focus {
@@ -76,6 +108,25 @@ export class BdsSelect extends LitElement {
76
108
  outline-offset: var(--bds-outline_offset);
77
109
  }
78
110
 
111
+ :host([error]) .select {
112
+ --bdc_color: var(--bdc_color--error);
113
+ }
114
+
115
+ .message {
116
+ margin-block-start: var(--bds-space_xxs);
117
+ font-size: var(--bds-font_size--body--s);
118
+ font-family: var(--bds-font_family--body);
119
+ }
120
+
121
+ .message--error {
122
+ color: var(--bds-color_error);
123
+ }
124
+
125
+ .message--hint {
126
+ color: var(--bds-color_on-bg--subtle);
127
+ font-style: italic;
128
+ }
129
+
79
130
  .chevron {
80
131
  position: absolute;
81
132
  inset-inline-end: var(--bds-space_s);
@@ -98,6 +149,9 @@ export class BdsSelect extends LitElement {
98
149
  value: { type: String },
99
150
  options: { type: String },
100
151
  placeholder: { type: String },
152
+ label: { type: String },
153
+ hint: { type: String },
154
+ error: { type: String, reflect: true },
101
155
  required: { type: Boolean, reflect: true },
102
156
  disabled: { type: Boolean, reflect: true },
103
157
  };
@@ -106,10 +160,14 @@ export class BdsSelect extends LitElement {
106
160
  declare value: string;
107
161
  declare options: string;
108
162
  declare placeholder: string;
163
+ declare label: string;
164
+ declare hint: string | undefined;
165
+ declare error: string | undefined;
109
166
  declare required: boolean;
110
167
  declare disabled: boolean;
111
168
 
112
169
  private _internals!: ElementInternals;
170
+ private readonly _uid = Math.random().toString(36).slice(2, 8);
113
171
 
114
172
  constructor() {
115
173
  super();
@@ -118,6 +176,7 @@ export class BdsSelect extends LitElement {
118
176
  this.value = '';
119
177
  this.options = '[]';
120
178
  this.placeholder = '';
179
+ this.label = '';
121
180
  this.required = false;
122
181
  this.disabled = false;
123
182
  }
@@ -144,18 +203,42 @@ export class BdsSelect extends LitElement {
144
203
 
145
204
  private _handleChange(e: Event) {
146
205
  this.value = (e.target as HTMLSelectElement).value;
206
+ this.dispatchEvent(new CustomEvent('bds-change', {
207
+ detail: { value: this.value },
208
+ bubbles: true,
209
+ composed: true,
210
+ }));
147
211
  }
148
212
 
149
213
  render() {
150
214
  const opts = this._options;
215
+ const id = `bds-select-${this._uid}`;
216
+ const hintId = `${id}-hint`;
217
+ const errorId = `${id}-error`;
218
+ const describedBy = [this.error && errorId, this.hint && hintId].filter(Boolean).join(' ') || undefined;
219
+ const hostAriaLabel = this.getAttribute('aria-label');
220
+
151
221
  return html`
222
+ ${this.label
223
+ ? html`
224
+ <label class="label" for=${id}>
225
+ ${this.label}
226
+ ${this.required ? html`<span class="required" aria-hidden="true">*</span>` : ''}
227
+ </label>
228
+ `
229
+ : ''}
152
230
  <div class="wrapper">
153
231
  <select
232
+ id=${id}
154
233
  class="select"
155
234
  name=${this.name}
156
235
  .value=${this.value}
157
236
  ?required=${this.required}
158
237
  ?disabled=${this.disabled}
238
+ aria-invalid=${this.error ? 'true' : 'false'}
239
+ aria-required=${this.required ? 'true' : 'false'}
240
+ aria-describedby=${describedBy ?? ''}
241
+ aria-label=${this.label ? nothing : (hostAriaLabel ?? nothing)}
159
242
  @change=${this._handleChange}
160
243
  >
161
244
  ${this.placeholder ? html`
@@ -175,6 +258,11 @@ export class BdsSelect extends LitElement {
175
258
  </svg>
176
259
  </span>
177
260
  </div>
261
+ ${this.error
262
+ ? html`<p id=${errorId} class="message message--error" role="alert">${this.error}</p>`
263
+ : this.hint
264
+ ? html`<p id=${hintId} class="message message--hint">${this.hint}</p>`
265
+ : ''}
178
266
  `;
179
267
  }
180
268
  }
@@ -38,4 +38,87 @@ describe('bds-slider', () => {
38
38
  it('is form-associated', () => {
39
39
  expect(BdsSlider.formAssociated).toBe(true);
40
40
  });
41
+
42
+ it('renders a label wired to the input via for/id', async () => {
43
+ const el = await fixture('<bds-slider name="volume" label="Volume"></bds-slider>');
44
+ const label = el.shadowRoot!.querySelector<HTMLLabelElement>('label')!;
45
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
46
+ expect(label).not.toBeNull();
47
+ expect(label.textContent?.trim()).toBe('Volume');
48
+ expect(label.getAttribute('for')).toBe(input.id);
49
+ expect(input.id).not.toBe('');
50
+ cleanup(el);
51
+ });
52
+
53
+ it('renders no label element when label is unset', async () => {
54
+ const el = await fixture('<bds-slider name="volume"></bds-slider>');
55
+ expect(el.shadowRoot!.querySelector('label')).toBeNull();
56
+ cleanup(el);
57
+ });
58
+
59
+ it('shows the current value next to the label when show-value is set', async () => {
60
+ const el = await fixture('<bds-slider name="volume" label="Volume" value="42" show-value></bds-slider>');
61
+ const value = el.shadowRoot!.querySelector('.value');
62
+ expect(value?.textContent?.trim()).toBe('42');
63
+ cleanup(el);
64
+ });
65
+
66
+ it('does not render a value element when show-value is unset', async () => {
67
+ const el = await fixture('<bds-slider name="volume" label="Volume" value="42"></bds-slider>');
68
+ expect(el.shadowRoot!.querySelector('.value')).toBeNull();
69
+ cleanup(el);
70
+ });
71
+
72
+ it('sets aria-invalid and aria-describedby and renders an error message when error is set', async () => {
73
+ const el = await fixture('<bds-slider name="volume" error="Too loud"></bds-slider>');
74
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
75
+ const message = el.shadowRoot!.querySelector<HTMLParagraphElement>('.message--error')!;
76
+ expect(input.getAttribute('aria-invalid')).toBe('true');
77
+ expect(input.getAttribute('aria-describedby')).toBe(message.id);
78
+ expect(message.textContent).toBe('Too loud');
79
+ expect(message.getAttribute('role')).toBe('alert');
80
+ cleanup(el);
81
+ });
82
+
83
+ it('renders a hint message and wires aria-describedby when hint is set (no error)', async () => {
84
+ const el = await fixture('<bds-slider name="volume" hint="Adjust to taste"></bds-slider>');
85
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
86
+ const message = el.shadowRoot!.querySelector<HTMLParagraphElement>('.message--hint')!;
87
+ expect(message).not.toBeNull();
88
+ expect(message.textContent).toBe('Adjust to taste');
89
+ expect(input.getAttribute('aria-invalid')).toBe('false');
90
+ expect(input.getAttribute('aria-describedby')).toBe(message.id);
91
+ cleanup(el);
92
+ });
93
+
94
+ it('fires a composed bds-change event that crosses the shadow boundary on release', async () => {
95
+ const el = await fixture('<bds-slider name="volume"></bds-slider>');
96
+ const values: number[] = [];
97
+ // A native `change` on the inner range input does not reliably cross the
98
+ // shadow boundary; `bds-change` is re-dispatched from the host so it does.
99
+ el.addEventListener('bds-change', (e: Event) => {
100
+ values.push((e as CustomEvent).detail.value);
101
+ });
102
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
103
+ input.value = '80';
104
+ input.dispatchEvent(new Event('change', { bubbles: true }));
105
+ expect(values).toEqual([80]);
106
+ cleanup(el);
107
+ });
108
+
109
+ it('restores the initial value attribute (not 0) on form reset', async () => {
110
+ const el = await fixture('<bds-slider name="volume" value="30" min="0" max="100"></bds-slider>') as BdsSlider;
111
+ el.value = 90;
112
+ el.formResetCallback();
113
+ expect(el.value).toBe(30);
114
+ cleanup(el);
115
+ });
116
+
117
+ it('clamps the restored reset value to min/max', async () => {
118
+ const el = await fixture('<bds-slider name="rating" value="3" min="1" max="5"></bds-slider>') as BdsSlider;
119
+ el.value = 5;
120
+ el.formResetCallback();
121
+ expect(el.value).toBe(3);
122
+ cleanup(el);
123
+ });
41
124
  });
@@ -4,27 +4,45 @@ import { LitElement, css, html } from 'lit';
4
4
  * `<bds-slider>` — form-associated Slider / Range Input custom element.
5
5
  *
6
6
  * Uses a native `<input type="range">` with a CSS fill track driven by
7
- * the `--slider_fill` custom property.
7
+ * the `--slider_fill` custom property. Renders an associated `<label>`
8
+ * when `label` is set, with `hint`/`error` messages wired to the input
9
+ * via `aria-describedby`.
8
10
  *
9
11
  * Attributes:
10
- * name — form field name
11
- * value — current value (default: 0)
12
- * min — minimum value (default: 0)
13
- * max — maximum value (default: 100)
14
- * step — step increment (default: 1)
15
- * disabled boolean
12
+ * name — form field name
13
+ * value — current value (default: 0)
14
+ * min — minimum value (default: 0)
15
+ * max — maximum value (default: 100)
16
+ * step — step increment (default: 1)
17
+ * label visible label text, associated with the input via `for`/`id`
18
+ * hint — helper text shown below the slider
19
+ * error — error message; when set the slider enters error state (aria-invalid)
20
+ * show-value — shows the current value next to the label
21
+ * disabled — boolean
16
22
  *
17
23
  * Events:
18
- * input — fired as the user drags
19
- * change — fired when the user releases
24
+ * input native event, fired continuously as the user drags
25
+ * bds-change — fired when the user releases; `detail: { value: number }`.
26
+ * Re-dispatched from the host (composed) so it reliably
27
+ * crosses the shadow boundary, unlike the native `change`.
20
28
  *
21
29
  * @example
22
- * <bds-slider name="volume" value="50" min="0" max="100" step="5"></bds-slider>
30
+ * <bds-slider name="volume" label="Volume" value="50" min="0" max="100" step="5"></bds-slider>
23
31
  */
24
32
  export class BdsSlider extends LitElement {
25
33
  static formAssociated = true;
26
34
 
27
35
  static styles = css`
36
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
37
+ here; otherwise elements with an explicit size + padding size as
38
+ content-box and layouts drift from the React (light-DOM) versions. */
39
+ :host,
40
+ *,
41
+ *::before,
42
+ *::after {
43
+ box-sizing: border-box;
44
+ }
45
+
28
46
  :host {
29
47
  display: block;
30
48
  }
@@ -34,6 +52,27 @@ export class BdsSlider extends LitElement {
34
52
  pointer-events: none;
35
53
  }
36
54
 
55
+ .label-row {
56
+ display: flex;
57
+ justify-content: space-between;
58
+ align-items: baseline;
59
+ margin-block-end: var(--bds-space_xxs);
60
+ }
61
+
62
+ .label {
63
+ display: block;
64
+ font-size: var(--bds-font_size--body--s);
65
+ font-family: var(--bds-font_family--body);
66
+ font-weight: var(--bds-font_weight--semibold);
67
+ color: var(--bds-color_on-bg);
68
+ }
69
+
70
+ .value {
71
+ font-size: var(--bds-font_size--body--s);
72
+ font-variant-numeric: tabular-nums;
73
+ color: var(--bds-color_on-bg--subtle);
74
+ }
75
+
37
76
  .track-wrapper {
38
77
  position: relative;
39
78
  display: flex;
@@ -41,13 +80,10 @@ export class BdsSlider extends LitElement {
41
80
  }
42
81
 
43
82
  .input {
44
- --slider_track-height: var(--bds-space_xxs);
45
- --slider_thumb-size: calc(var(--bds-space_s) * 2);
46
-
47
83
  color: var(--slider_color, var(--bds-color_on-bg));
48
84
  inline-size: 100%;
49
85
  appearance: none;
50
- block-size: var(--slider_track-height);
86
+ block-size: var(--slider_track-height, var(--bds-space_xxs));
51
87
  border-radius: var(--slider_track-radius, var(--bds-border_radius--full));
52
88
  background: linear-gradient(
53
89
  to right,
@@ -61,10 +97,20 @@ export class BdsSlider extends LitElement {
61
97
  transition: var(--bds-animation_transition);
62
98
  }
63
99
 
100
+ :host([error]) .input {
101
+ background: linear-gradient(
102
+ to right,
103
+ var(--slider_color--error, var(--bds-color_error)) 0%,
104
+ var(--slider_color--error, var(--bds-color_error)) var(--slider_fill, 0%),
105
+ var(--slider_track-bg, var(--bds-color_bg--subtle)) var(--slider_fill, 0%),
106
+ var(--slider_track-bg, var(--bds-color_bg--subtle)) 100%
107
+ );
108
+ }
109
+
64
110
  .input::-webkit-slider-thumb {
65
111
  appearance: none;
66
- inline-size: var(--slider_thumb-size);
67
- block-size: var(--slider_thumb-size);
112
+ inline-size: var(--slider_thumb-size, calc(var(--bds-space_s) * 2));
113
+ block-size: var(--slider_thumb-size, calc(var(--bds-space_s) * 2));
68
114
  border-radius: var(--slider_thumb-radius, var(--bds-border_radius--circle));
69
115
  background-color: var(--slider_color-active, var(--bdc-color_active));
70
116
  box-shadow: var(--bds-shadow_s);
@@ -72,9 +118,13 @@ export class BdsSlider extends LitElement {
72
118
  transition: var(--bds-animation_transition);
73
119
  }
74
120
 
121
+ :host([error]) .input::-webkit-slider-thumb {
122
+ background-color: var(--slider_color--error, var(--bds-color_error));
123
+ }
124
+
75
125
  .input::-moz-range-thumb {
76
- inline-size: var(--slider_thumb-size);
77
- block-size: var(--slider_thumb-size);
126
+ inline-size: var(--slider_thumb-size, calc(var(--bds-space_s) * 2));
127
+ block-size: var(--slider_thumb-size, calc(var(--bds-space_s) * 2));
78
128
  border: none;
79
129
  border-radius: var(--slider_thumb-radius, var(--bds-border_radius--circle));
80
130
  background-color: var(--slider_color-active, var(--bdc-color_active));
@@ -82,6 +132,10 @@ export class BdsSlider extends LitElement {
82
132
  cursor: pointer;
83
133
  }
84
134
 
135
+ :host([error]) .input::-moz-range-thumb {
136
+ background-color: var(--slider_color--error, var(--bds-color_error));
137
+ }
138
+
85
139
  .input:disabled {
86
140
  opacity: 0.4;
87
141
  cursor: not-allowed;
@@ -93,6 +147,21 @@ export class BdsSlider extends LitElement {
93
147
  border-radius: var(--slider_track-radius, var(--bds-border_radius--full));
94
148
  }
95
149
 
150
+ .message {
151
+ margin-block-start: var(--bds-space_xxs);
152
+ font-size: var(--bds-font_size--body--s);
153
+ font-family: var(--bds-font_family--body);
154
+ }
155
+
156
+ .message--error {
157
+ color: var(--bds-color_error);
158
+ }
159
+
160
+ .message--hint {
161
+ color: var(--bds-color_on-bg--subtle);
162
+ font-style: italic;
163
+ }
164
+
96
165
  @media (prefers-reduced-motion: reduce) {
97
166
  .input,
98
167
  .input::-webkit-slider-thumb,
@@ -103,12 +172,16 @@ export class BdsSlider extends LitElement {
103
172
  `;
104
173
 
105
174
  static properties = {
106
- name: { type: String, reflect: true },
107
- value: { type: Number },
108
- min: { type: Number },
109
- max: { type: Number },
110
- step: { type: Number },
111
- disabled: { type: Boolean, reflect: true },
175
+ name: { type: String, reflect: true },
176
+ value: { type: Number },
177
+ min: { type: Number },
178
+ max: { type: Number },
179
+ step: { type: Number },
180
+ disabled: { type: Boolean, reflect: true },
181
+ label: { type: String },
182
+ hint: { type: String },
183
+ error: { type: String, reflect: true },
184
+ showValue: { type: Boolean, attribute: 'show-value', reflect: true },
112
185
  };
113
186
 
114
187
  declare name: string;
@@ -117,8 +190,14 @@ export class BdsSlider extends LitElement {
117
190
  declare max: number;
118
191
  declare step: number;
119
192
  declare disabled: boolean;
193
+ declare label: string;
194
+ declare hint: string | undefined;
195
+ declare error: string | undefined;
196
+ declare showValue: boolean;
120
197
 
121
198
  private _internals!: ElementInternals;
199
+ private readonly _uid = Math.random().toString(36).slice(2, 8);
200
+ private _initialValue = 0;
122
201
 
123
202
  constructor() {
124
203
  super();
@@ -129,6 +208,18 @@ export class BdsSlider extends LitElement {
129
208
  this.max = 100;
130
209
  this.step = 1;
131
210
  this.disabled = false;
211
+ this.label = '';
212
+ this.hint = undefined;
213
+ this.error = undefined;
214
+ this.showValue = false;
215
+ }
216
+
217
+ connectedCallback() {
218
+ super.connectedCallback();
219
+ // Capture the value as it stands when this element enters the DOM (i.e.
220
+ // the parsed `value` attribute, or the constructor default), clamped to
221
+ // min/max. formResetCallback restores this rather than hardcoding 0.
222
+ this._initialValue = this._clamp(this.value);
132
223
  }
133
224
 
134
225
  updated(changed: Map<string, unknown>) {
@@ -139,8 +230,12 @@ export class BdsSlider extends LitElement {
139
230
  }
140
231
 
141
232
  formResetCallback() {
142
- this.value = 0;
143
- this._internals.setFormValue?.('0');
233
+ this.value = this._initialValue;
234
+ this._internals.setFormValue?.(String(this.value));
235
+ }
236
+
237
+ private _clamp(v: number): number {
238
+ return Math.min(this.max, Math.max(this.min, v));
144
239
  }
145
240
 
146
241
  private get _fillPct(): number {
@@ -153,22 +248,55 @@ export class BdsSlider extends LitElement {
153
248
  this.value = parseFloat((e.target as HTMLInputElement).value);
154
249
  }
155
250
 
251
+ private _handleChange(e: Event) {
252
+ this.value = parseFloat((e.target as HTMLInputElement).value);
253
+ // The native `change` event does not reliably cross the shadow
254
+ // boundary, so re-dispatch a composed bds-change from the host.
255
+ this.dispatchEvent(new CustomEvent('bds-change', {
256
+ detail: { value: this.value },
257
+ bubbles: true,
258
+ composed: true,
259
+ }));
260
+ }
261
+
156
262
  render() {
263
+ const id = `bds-slider-${this._uid}`;
264
+ const hintId = `${id}-hint`;
265
+ const errorId = `${id}-error`;
266
+ const describedBy = [this.error && errorId, this.hint && hintId].filter(Boolean).join(' ') || undefined;
267
+
157
268
  return html`
269
+ ${this.label
270
+ ? html`
271
+ <div class="label-row">
272
+ <label class="label" for=${id}>${this.label}</label>
273
+ ${this.showValue ? html`<span class="value">${this.value}</span>` : ''}
274
+ </div>
275
+ `
276
+ : ''}
158
277
  <div class="track-wrapper">
159
278
  <input
160
279
  type="range"
161
280
  class="input"
281
+ id=${id}
162
282
  name=${this.name}
163
283
  .value=${String(this.value)}
164
284
  min=${this.min}
165
285
  max=${this.max}
166
286
  step=${this.step}
167
287
  ?disabled=${this.disabled}
288
+ aria-invalid=${this.error ? 'true' : 'false'}
289
+ aria-describedby=${describedBy ?? ''}
168
290
  style="--slider_fill: ${this._fillPct}%"
169
291
  @input=${this._handleInput}
292
+ @change=${this._handleChange}
170
293
  />
171
294
  </div>
295
+ ${this.error
296
+ ? html`<p id=${errorId} class="message message--error" role="alert">${this.error}</p>`
297
+ : this.hint
298
+ ? html`<p id=${hintId} class="message message--hint">${this.hint}</p>`
299
+ : ''}
172
300
  `;
173
301
  }
174
302
  }
@@ -59,4 +59,72 @@ describe('bds-switch', () => {
59
59
  it('is form-associated', () => {
60
60
  expect(BdsSwitch.formAssociated).toBe(true);
61
61
  });
62
+
63
+ it('constrains the overlay input to a positioned track-wrapper (not the whole component)', async () => {
64
+ const el = await fixture('<bds-switch name="notify">Notifications</bds-switch>');
65
+ const wrapper = el.shadowRoot!.querySelector('.track-wrapper');
66
+ expect(wrapper).not.toBeNull();
67
+ expect(wrapper!.querySelector('input.input')).not.toBeNull();
68
+ expect(wrapper!.querySelector('.track')).not.toBeNull();
69
+ cleanup(el);
70
+ });
71
+
72
+ it('fires a composed bds-change event when toggled', async () => {
73
+ const el = await fixture('<bds-switch name="notify">Notifications</bds-switch>') as BdsSwitch;
74
+ const events: CustomEvent[] = [];
75
+ el.addEventListener('bds-change', (e: Event) => {
76
+ events.push(e as CustomEvent);
77
+ });
78
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
79
+ input.checked = true;
80
+ input.dispatchEvent(new Event('change', { bubbles: true }));
81
+ expect(events).toHaveLength(1);
82
+ expect(events[0].composed).toBe(true);
83
+ expect(events[0].detail).toEqual({ checked: true });
84
+ cleanup(el);
85
+ });
86
+
87
+ it('defaults to size="medium"', async () => {
88
+ const el = await fixture('<bds-switch name="notify">Notifications</bds-switch>');
89
+ expect(el.getAttribute('size')).toBe('medium');
90
+ cleanup(el);
91
+ });
92
+
93
+ it('reflects size property to attribute', async () => {
94
+ const el = await fixture('<bds-switch name="notify">Notifications</bds-switch>') as BdsSwitch;
95
+ el.size = 'small';
96
+ await el.updateComplete;
97
+ expect(el.getAttribute('size')).toBe('small');
98
+ cleanup(el);
99
+ });
100
+
101
+ it('marks the input aria-invalid when error is set', async () => {
102
+ const el = await fixture('<bds-switch name="notify" error="Required">Notifications</bds-switch>');
103
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
104
+ expect(input.getAttribute('aria-invalid')).toBe('true');
105
+ cleanup(el);
106
+ });
107
+
108
+ it('input is not aria-invalid when error is unset', async () => {
109
+ const el = await fixture('<bds-switch name="notify">Notifications</bds-switch>');
110
+ const input = el.shadowRoot!.querySelector<HTMLInputElement>('input')!;
111
+ expect(input.getAttribute('aria-invalid')).toBe('false');
112
+ cleanup(el);
113
+ });
114
+
115
+ it('restores the initial checked state on form reset', async () => {
116
+ const el = await fixture('<bds-switch name="notify" checked>Notifications</bds-switch>') as BdsSwitch;
117
+ el.checked = false;
118
+ el.formResetCallback();
119
+ expect(el.checked).toBe(true);
120
+ cleanup(el);
121
+ });
122
+
123
+ it('restores unchecked as the initial state when checked was never set', async () => {
124
+ const el = await fixture('<bds-switch name="notify">Notifications</bds-switch>') as BdsSwitch;
125
+ el.checked = true;
126
+ el.formResetCallback();
127
+ expect(el.checked).toBe(false);
128
+ cleanup(el);
129
+ });
62
130
  });