@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 ComboboxOption {
4
4
  value: string;
@@ -17,6 +17,9 @@ export interface ComboboxOption {
17
17
  * value — currently selected value
18
18
  * options — JSON array of `{ value, label, disabled? }` option objects
19
19
  * placeholder — input placeholder text
20
+ * label — visible label text (associated to the input via `<label for>`)
21
+ * hint — helper text shown below the input
22
+ * error — error message; when set the input enters error state
20
23
  * disabled — boolean
21
24
  *
22
25
  * Events:
@@ -25,6 +28,7 @@ export interface ComboboxOption {
25
28
  * @example
26
29
  * <bds-combobox
27
30
  * name="country"
31
+ * label="Country"
28
32
  * placeholder="Search…"
29
33
  * options='[{"value":"nl","label":"Netherlands"},{"value":"be","label":"Belgium"}]'
30
34
  * ></bds-combobox>
@@ -33,6 +37,16 @@ export class BdsCombobox extends LitElement {
33
37
  static formAssociated = true;
34
38
 
35
39
  static styles = css`
40
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
41
+ here; otherwise elements with an explicit size + padding size as
42
+ content-box and layouts drift from the React (light-DOM) versions. */
43
+ :host,
44
+ *,
45
+ *::before,
46
+ *::after {
47
+ box-sizing: border-box;
48
+ }
49
+
36
50
  :host {
37
51
  display: block;
38
52
  position: relative;
@@ -43,6 +57,15 @@ export class BdsCombobox extends LitElement {
43
57
  pointer-events: none;
44
58
  }
45
59
 
60
+ .label {
61
+ display: block;
62
+ font-size: var(--bds-font_size--body--s);
63
+ font-family: var(--bds-font_family--body);
64
+ font-weight: var(--bds-font_weight--semibold);
65
+ color: var(--bds-color_on-bg);
66
+ margin-block-end: var(--bds-space_xxs);
67
+ }
68
+
46
69
  .wrapper {
47
70
  position: relative;
48
71
  }
@@ -52,8 +75,8 @@ export class BdsCombobox extends LitElement {
52
75
  font-family: var(--bds-font_family--body);
53
76
  font-size: var(--bds-font_size--body);
54
77
  padding: var(--bds-space_s);
55
- padding-inline-end: var(--bds-space_xl);
56
- border: none;
78
+ padding-inline-end: var(--bds-space_xxl);
79
+ border: var(--combobox_border, none);
57
80
  --bdc_color: var(--combobox_border-color, currentcolor);
58
81
  --bdc-outline_radius: var(--bds-border_radius--full);
59
82
 
@@ -74,6 +97,14 @@ export class BdsCombobox extends LitElement {
74
97
  outline-offset: var(--bds-outline_offset);
75
98
  }
76
99
 
100
+ :host([error]) .input {
101
+ --bdc_color: var(--bdc_color--error);
102
+ }
103
+
104
+ :host([error]) .input:focus {
105
+ --bdc_color: var(--bdc_color--error);
106
+ }
107
+
77
108
  .chevron {
78
109
  position: absolute;
79
110
  inset-inline-end: var(--bds-space_s);
@@ -92,31 +123,39 @@ export class BdsCombobox extends LitElement {
92
123
 
93
124
  .listbox {
94
125
  position: absolute;
95
- inset-block-start: calc(100% + var(--bds-space_xs));
126
+ inset-block-start: calc(100% + var(--bds-space_xxs));
96
127
  inset-inline-start: 0;
97
128
  inline-size: 100%;
98
129
  max-block-size: 15rem;
99
- overflow-y: auto;
100
- background-color: var(--combobox_list-bg, var(--bds-color_bg));
101
- border-radius: var(--bds-border_radius--s);
102
- box-shadow: var(--bds-shadow_m);
103
- z-index: var(--combobox_z-index, 100);
104
- padding-block: var(--bds-space_xs);
130
+ overflow-block: auto;
131
+ list-style: none;
132
+ margin: 0;
133
+ border: var(--combobox_listbox-border, none);
134
+ --bdc_color: currentcolor;
135
+ --bdc-outline_radius: var(--bds-border_radius--s);
136
+
137
+ border-radius: var(--combobox_listbox-radius, var(--bdc-outline_radius));
138
+ background-color: var(--combobox_color_bg, var(--bds-color_bg));
139
+ color: var(--combobox_on-color, var(--bds-color_on-bg));
140
+ box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--combobox_listbox-shadow, var(--bds-shadow_m));
141
+ z-index: var(--combobox_z-index, var(--bds-z-index_dropdown));
142
+ padding: var(--bds-space_xxs) 0;
105
143
  }
106
144
 
107
145
  .option {
108
146
  display: block;
109
- padding: var(--bds-space_s) var(--bds-space_m);
147
+ padding: var(--bds-space_xs) var(--bds-space_m);
110
148
  cursor: pointer;
111
149
  font-family: var(--bds-font_family--body);
112
150
  font-size: var(--bds-font_size--body);
113
- color: var(--bds-color_on-bg);
151
+ color: var(--combobox_on-color, var(--bds-color_on-bg));
114
152
  transition: background-color var(--bds-animation_transition-duration) var(--bds-animation_easing);
115
153
  }
116
154
 
117
155
  .option:hover,
118
156
  .option[aria-selected='true'] {
119
- background-color: var(--bds-color_bg--subtle);
157
+ background-color: var(--combobox_option-bg--highlighted, var(--bds-color_bg--subtle));
158
+ color: var(--combobox_option-color--highlighted, var(--bds-color_interactive_on-bg));
120
159
  }
121
160
 
122
161
  .option[aria-disabled='true'] {
@@ -125,7 +164,8 @@ export class BdsCombobox extends LitElement {
125
164
  }
126
165
 
127
166
  .option.--focused {
128
- background-color: var(--bds-color_bg--subtle);
167
+ background-color: var(--combobox_option-bg--highlighted, var(--bds-color_bg--subtle));
168
+ color: var(--combobox_option-color--highlighted, var(--bds-color_interactive_on-bg));
129
169
  outline: none;
130
170
  }
131
171
 
@@ -135,6 +175,21 @@ export class BdsCombobox extends LitElement {
135
175
  font-size: var(--bds-font_size--body--s);
136
176
  color: var(--bds-color_on-bg--subtle);
137
177
  }
178
+
179
+ .message {
180
+ margin-block-start: var(--bds-space_xxs);
181
+ font-size: var(--bds-font_size--body--s);
182
+ font-family: var(--bds-font_family--body);
183
+ }
184
+
185
+ .message--error {
186
+ color: var(--bds-color_error);
187
+ }
188
+
189
+ .message--hint {
190
+ color: var(--bds-color_on-bg--subtle);
191
+ font-style: italic;
192
+ }
138
193
  `;
139
194
 
140
195
  static properties = {
@@ -142,6 +197,9 @@ export class BdsCombobox extends LitElement {
142
197
  value: { type: String },
143
198
  options: { type: String },
144
199
  placeholder: { type: String },
200
+ label: { type: String },
201
+ hint: { type: String },
202
+ error: { type: String, reflect: true },
145
203
  disabled: { type: Boolean, reflect: true },
146
204
  };
147
205
 
@@ -149,9 +207,13 @@ export class BdsCombobox extends LitElement {
149
207
  declare value: string;
150
208
  declare options: string;
151
209
  declare placeholder: string;
210
+ declare label: string;
211
+ declare hint: string | undefined;
212
+ declare error: string | undefined;
152
213
  declare disabled: boolean;
153
214
 
154
215
  private _internals!: ElementInternals;
216
+ private readonly _uid = Math.random().toString(36).slice(2, 8);
155
217
  private _open = false;
156
218
  private _query = '';
157
219
  private _focusedIndex = -1;
@@ -163,6 +225,7 @@ export class BdsCombobox extends LitElement {
163
225
  this.value = '';
164
226
  this.options = '[]';
165
227
  this.placeholder = '';
228
+ this.label = '';
166
229
  this.disabled = false;
167
230
  }
168
231
 
@@ -280,16 +343,32 @@ export class BdsCombobox extends LitElement {
280
343
  render() {
281
344
  const filtered = this._filtered;
282
345
  const inputValue = this._open ? this._query : this._displayLabel;
346
+ const id = `bds-combobox-${this._uid}`;
347
+ const listboxId = `${id}-listbox`;
348
+ const hintId = `${id}-hint`;
349
+ const errorId = `${id}-error`;
350
+ const describedBy = [this.error && errorId, this.hint && hintId].filter(Boolean).join(' ') || undefined;
351
+ const activeDescendant =
352
+ this._focusedIndex >= 0 && this._focusedIndex < filtered.length
353
+ ? `${id}-option-${this._focusedIndex}`
354
+ : undefined;
283
355
 
284
356
  return html`
357
+ ${this.label ? html`<label class="label" for=${id}>${this.label}</label>` : ''}
285
358
  <div class="wrapper">
286
359
  <input
360
+ id=${id}
287
361
  type="text"
288
362
  class="input"
289
363
  role="combobox"
290
364
  aria-expanded=${this._open}
291
365
  aria-autocomplete="list"
292
366
  aria-haspopup="listbox"
367
+ aria-controls=${listboxId}
368
+ aria-activedescendant=${activeDescendant ?? nothing}
369
+ aria-invalid=${this.error ? 'true' : 'false'}
370
+ aria-describedby=${describedBy ?? nothing}
371
+ autocomplete="off"
293
372
  name=${this.name}
294
373
  placeholder=${this.placeholder}
295
374
  .value=${inputValue}
@@ -305,11 +384,12 @@ export class BdsCombobox extends LitElement {
305
384
  </svg>
306
385
  </span>
307
386
  ${this._open ? html`
308
- <ul class="listbox" role="listbox" aria-label="Options">
387
+ <ul id=${listboxId} class="listbox" role="listbox" aria-label="Options">
309
388
  ${filtered.length === 0
310
- ? html`<li class="no-results">No results</li>`
389
+ ? html`<li class="no-results" role="presentation">No results</li>`
311
390
  : filtered.map((opt, i) => html`
312
391
  <li
392
+ id="${id}-option-${i}"
313
393
  class="option ${i === this._focusedIndex ? '--focused' : ''}"
314
394
  role="option"
315
395
  aria-selected=${opt.value === this.value}
@@ -321,6 +401,11 @@ export class BdsCombobox extends LitElement {
321
401
  </ul>
322
402
  ` : ''}
323
403
  </div>
404
+ ${this.error
405
+ ? html`<p id=${errorId} class="message message--error" role="alert">${this.error}</p>`
406
+ : this.hint
407
+ ? html`<p id=${hintId} class="message message--hint">${this.hint}</p>`
408
+ : ''}
324
409
  `;
325
410
  }
326
411
  }
@@ -61,4 +61,162 @@ describe('bds-field-group', () => {
61
61
  expect(el.style.getPropertyValue('--fieldGroup_field-count')).toBe('3');
62
62
  cleanup(el);
63
63
  });
64
+
65
+ it('renders the auto-collapse probe elements in the shadow DOM', async () => {
66
+ const el = await fixture('<bds-field-group></bds-field-group>');
67
+ expect(el.shadowRoot!.querySelector('.probeContainer')).not.toBeNull();
68
+ expect(el.shadowRoot!.querySelector('.probe')).not.toBeNull();
69
+ cleanup(el);
70
+ });
71
+
72
+ describe('disabled propagation to slotted controls', () => {
73
+ // A shadow-root <fieldset disabled> cannot disable light-DOM children
74
+ // projected through a <slot> — a slotted element's actual DOM parent
75
+ // stays the host, not the shadow fieldset, so the UA's fieldset-disables-
76
+ // descendants algorithm never reaches them. The component sets
77
+ // `.disabled` on each slotted control directly instead.
78
+
79
+ it('propagates disabled to slotted form controls', async () => {
80
+ const el = await fixture(
81
+ '<bds-field-group disabled><input id="a" /><input id="b" /></bds-field-group>',
82
+ ) as BdsFieldGroup;
83
+ const a = el.querySelector('#a') as HTMLInputElement;
84
+ const b = el.querySelector('#b') as HTMLInputElement;
85
+ expect(a.disabled).toBe(true);
86
+ expect(b.disabled).toBe(true);
87
+ cleanup(el);
88
+ });
89
+
90
+ it('re-enables slotted controls when disabled is cleared', async () => {
91
+ const el = await fixture(
92
+ '<bds-field-group disabled><input id="a" /></bds-field-group>',
93
+ ) as BdsFieldGroup;
94
+ el.disabled = false;
95
+ await el.updateComplete;
96
+ const a = el.querySelector('#a') as HTMLInputElement;
97
+ expect(a.disabled).toBe(false);
98
+ cleanup(el);
99
+ });
100
+
101
+ it('propagates disabled to controls slotted in after the group is already disabled', async () => {
102
+ const el = await fixture('<bds-field-group disabled></bds-field-group>') as BdsFieldGroup;
103
+ const input = document.createElement('input');
104
+ input.id = 'late';
105
+ el.appendChild(input);
106
+ // slotchange fires asynchronously; allow a microtask.
107
+ await new Promise(r => requestAnimationFrame(() => r(null)));
108
+ expect(input.disabled).toBe(true);
109
+ cleanup(el);
110
+ });
111
+
112
+ it('does not re-enable a slotted control the consumer had individually disabled', async () => {
113
+ const el = await fixture(
114
+ '<bds-field-group><input id="a" disabled /><input id="b" /></bds-field-group>',
115
+ ) as BdsFieldGroup;
116
+ const a = el.querySelector('#a') as HTMLInputElement;
117
+ const b = el.querySelector('#b') as HTMLInputElement;
118
+
119
+ el.disabled = true;
120
+ await el.updateComplete;
121
+ expect(a.disabled).toBe(true);
122
+ expect(b.disabled).toBe(true);
123
+
124
+ el.disabled = false;
125
+ await el.updateComplete;
126
+ expect(a.disabled).toBe(true); // consumer-set — must stay disabled
127
+ expect(b.disabled).toBe(false); // group-set — re-enabled
128
+ cleanup(el);
129
+ });
130
+ });
131
+
132
+ describe('auto-collapse (mocked ResizeObserver)', () => {
133
+ // jsdom has no ResizeObserver. Install a mock that records each
134
+ // constructed observer and the elements it was told to watch, so tests
135
+ // can drive its callback directly — mirrors the mock used in
136
+ // FieldGroup.spec.tsx for the React counterpart of this same mechanism.
137
+ class MockResizeObserver {
138
+ callback: ResizeObserverCallback;
139
+ observed: Element[] = [];
140
+
141
+ constructor(callback: ResizeObserverCallback) {
142
+ this.callback = callback;
143
+ instances.push(this);
144
+ }
145
+
146
+ observe(el: Element) {
147
+ this.observed.push(el);
148
+ }
149
+
150
+ unobserve() {}
151
+
152
+ disconnect() {}
153
+ }
154
+
155
+ let instances: MockResizeObserver[] = [];
156
+ const originalResizeObserver = globalThis.ResizeObserver;
157
+
158
+ const fireResize = (
159
+ instance: MockResizeObserver,
160
+ fieldsetWidth: number,
161
+ probeWidth: number,
162
+ ) => {
163
+ const [fieldsetEl, probeEl] = instance.observed;
164
+ instance.callback(
165
+ [
166
+ { target: fieldsetEl, contentRect: { width: fieldsetWidth } },
167
+ { target: probeEl, contentRect: { width: probeWidth } },
168
+ ] as unknown as ResizeObserverEntry[],
169
+ instance as unknown as ResizeObserver,
170
+ );
171
+ };
172
+
173
+ beforeEach(() => {
174
+ instances = [];
175
+ (globalThis as unknown as { ResizeObserver: typeof ResizeObserver }).ResizeObserver =
176
+ MockResizeObserver as unknown as typeof ResizeObserver;
177
+ });
178
+
179
+ afterEach(() => {
180
+ if (originalResizeObserver) {
181
+ (globalThis as unknown as { ResizeObserver: typeof ResizeObserver }).ResizeObserver =
182
+ originalResizeObserver;
183
+ } else {
184
+ delete (globalThis as unknown as Record<string, unknown>).ResizeObserver;
185
+ }
186
+ });
187
+
188
+ it('sets data-collapsed when the fieldset is narrower than the derived threshold', async () => {
189
+ const el = await fixture(
190
+ '<bds-field-group><input /><input /></bds-field-group>',
191
+ ) as BdsFieldGroup;
192
+ expect(instances).toHaveLength(1);
193
+
194
+ fireResize(instances[0], 200, 400);
195
+ expect(el.hasAttribute('data-collapsed')).toBe(true);
196
+ cleanup(el);
197
+ });
198
+
199
+ it('clears data-collapsed once the fieldset is wide enough for the row', async () => {
200
+ const el = await fixture(
201
+ '<bds-field-group><input /><input /></bds-field-group>',
202
+ ) as BdsFieldGroup;
203
+
204
+ fireResize(instances[0], 200, 400);
205
+ expect(el.hasAttribute('data-collapsed')).toBe(true);
206
+
207
+ fireResize(instances[0], 600, 400);
208
+ expect(el.hasAttribute('data-collapsed')).toBe(false);
209
+ cleanup(el);
210
+ });
211
+
212
+ it('never collapses the vertical variant', async () => {
213
+ const el = await fixture(
214
+ '<bds-field-group variant="vertical"><input /></bds-field-group>',
215
+ ) as BdsFieldGroup;
216
+
217
+ fireResize(instances[0], 50, 400);
218
+ expect(el.hasAttribute('data-collapsed')).toBe(false);
219
+ cleanup(el);
220
+ });
221
+ });
64
222
  });
@@ -6,14 +6,20 @@ export type FieldGroupVariant = 'horizontal' | 'vertical';
6
6
  * `<bds-field-group>` — framework-agnostic FieldGroup custom element.
7
7
  *
8
8
  * Semantically groups related form fields under a single `<fieldset>` and
9
- * lays them out either horizontally (with a CSS container query that
10
- * collapses to a vertical stack when the FieldGroup itself is too narrow)
11
- * or vertically. Mirrors the React `FieldGroup` component.
9
+ * lays them out either horizontally (auto-collapsing to a vertical stack
10
+ * when the FieldGroup itself is too narrow to fit a full row) or
11
+ * vertically. Mirrors the React `FieldGroup` component.
12
12
  *
13
13
  * Attributes:
14
14
  * variant — "horizontal" (default) | "vertical"
15
15
  * legend — optional legend text rendered above the fields
16
- * disabled — boolean; forwarded to the inner <fieldset>
16
+ * disabled — boolean; forwarded to the inner <fieldset> AND propagated to
17
+ * each directly-slotted form control. A shadow-root `<fieldset disabled>`
18
+ * cannot disable light-DOM children projected through a `<slot>` — its
19
+ * "descendant" is defined over the DOM tree, and a slotted element's
20
+ * actual parent stays the host, not the shadow fieldset — so the WC
21
+ * sets `.disabled` on each slotted control directly (see
22
+ * `_syncDisabledToSlotted`).
17
23
  *
18
24
  * Slots:
19
25
  * (default) — form fields (any element). The slotted-element count is
@@ -21,6 +27,16 @@ export type FieldGroupVariant = 'horizontal' | 'vertical';
21
27
  * `--fieldGroup_field-count` custom property, which the auto-derived
22
28
  * collapse threshold reads.
23
29
  *
30
+ * Auto-collapse mechanism (mirrors FieldGroup.tsx):
31
+ * `@container` query *conditions* cannot reference custom properties — a
32
+ * var() inside a container-query feature value is invalid CSS and is
33
+ * silently dropped, so it can never fire. Instead, an invisible `.probe`
34
+ * element's own inline-size resolves --fieldGroup_collapse-threshold
35
+ * through a normal property value (where var() is valid); a
36
+ * ResizeObserver compares the probe's measured pixel width against the
37
+ * `<fieldset>`'s own width and toggles a `data-collapsed` attribute on
38
+ * the host, which drives the CSS.
39
+ *
24
40
  * @example
25
41
  * <bds-field-group variant="horizontal" legend="Contact details">
26
42
  * <bds-form-input label="First name" name="first"></bds-form-input>
@@ -30,18 +46,25 @@ export type FieldGroupVariant = 'horizontal' | 'vertical';
30
46
  */
31
47
  export class BdsFieldGroup extends LitElement {
32
48
  static styles = css`
49
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
50
+ here; otherwise elements with an explicit size + padding size as
51
+ content-box and layouts drift from the React (light-DOM) versions. */
52
+ :host,
53
+ *,
54
+ *::before,
55
+ *::after {
56
+ box-sizing: border-box;
57
+ }
58
+
33
59
  :host {
34
60
  display: block;
35
61
 
36
- /* Establish an inline-size containment context so the @container rule
37
- queries the host's own width — independent of the viewport. */
38
- container-type: inline-size;
39
- container-name: field-group;
40
-
41
62
  /* Auto-derived collapse threshold (mirror of the React component).
42
63
  --fieldGroup_field-count is set inline by _onSlotChange; the other
43
64
  tokens use foundation-default fallbacks so the calc rebuilds when
44
- a consumer overrides --fieldGroup_min-field-width or _gap. */
65
+ a consumer overrides --fieldGroup_min-field-width or _gap. Read by
66
+ .probe's inline-size below — see the class doc comment for why a
67
+ direct @container condition can't use this. */
45
68
  --fieldGroup_collapse-threshold:
46
69
  calc(
47
70
  var(--fieldGroup_field-count, 1)
@@ -71,7 +94,8 @@ export class BdsFieldGroup extends LitElement {
71
94
 
72
95
  color:
73
96
  var(--fieldGroup_legend-color, var(--bds-color_on-bg));
74
- font-family: var(--bds-font_family--body);
97
+ font-family:
98
+ var(--fieldGroup_legend-font-family, var(--bds-font_family--body));
75
99
  font-size:
76
100
  var(--fieldGroup_legend-font-size, var(--bds-font_size--heading-3));
77
101
  font-weight:
@@ -80,6 +104,12 @@ export class BdsFieldGroup extends LitElement {
80
104
  var(--fieldGroup_legend-line-height, var(--bds-font_line-height--heading));
81
105
  }
82
106
 
107
+ /* Disabled group: dim the legend. Slotted fields dim via their own
108
+ :host([disabled]) rule. Parity with the React FieldGroup. */
109
+ :host([disabled]) .legend {
110
+ opacity: 0.5;
111
+ }
112
+
83
113
  .fields {
84
114
  display: flex;
85
115
  flex-direction: column;
@@ -95,17 +125,38 @@ export class BdsFieldGroup extends LitElement {
95
125
  min-inline-size: 0;
96
126
  }
97
127
 
98
- /* Auto-collapse: when the host's inline-size can't fit a complete
99
- horizontal row, switch to a single-column stack. Threshold scales
100
- with the actual slotted-element count (see :host calc above). */
101
- @container field-group (max-inline-size: var(--fieldGroup_collapse-threshold)) {
102
- :host([variant='horizontal']) .fields {
103
- flex-direction: column;
104
- }
128
+ /* Zero-size, overflow-clipped box housing .probe. .probe's inline-size
129
+ is intentionally larger than the fieldset whenever the layout should
130
+ collapse, so it must be fully contained here never left to poke
131
+ into the page but clipping only affects paint/scroll, not .probe's
132
+ own resolved box size, so ResizeObserver still reports its true
133
+ width. */
134
+ .probeContainer {
135
+ position: relative;
136
+ inline-size: 0;
137
+ block-size: 0;
138
+ overflow: hidden;
139
+ }
105
140
 
106
- :host([variant='horizontal']) .fields ::slotted(*) {
107
- flex: 1 1 auto;
108
- }
141
+ .probe {
142
+ position: absolute;
143
+ inset-block-start: 0;
144
+ inset-inline-start: 0;
145
+ block-size: 0;
146
+ inline-size: var(--fieldGroup_collapse-threshold);
147
+ visibility: hidden;
148
+ }
149
+
150
+ /* JS (see _onResize/_updateCollapsed) toggles data-collapsed on the host
151
+ once the fieldset's own inline-size can no longer fit a complete
152
+ horizontal row. Threshold scales with the actual slotted-element
153
+ count (see :host calc above). */
154
+ :host([variant='horizontal'][data-collapsed='true']) .fields {
155
+ flex-direction: column;
156
+ }
157
+
158
+ :host([variant='horizontal'][data-collapsed='true']) .fields ::slotted(*) {
159
+ flex: 1 1 auto;
109
160
  }
110
161
  `;
111
162
 
@@ -119,6 +170,17 @@ export class BdsFieldGroup extends LitElement {
119
170
  declare legend: string;
120
171
  declare disabled: boolean;
121
172
 
173
+ private _ro?: ResizeObserver;
174
+ private _fieldsetEl?: HTMLFieldSetElement;
175
+ private _probeEl?: HTMLElement;
176
+ private _fieldsetSize = 0;
177
+ private _thresholdSize = 0;
178
+
179
+ // Slotted controls this instance disabled on the group's behalf, so
180
+ // re-enabling the group never overrides a control the consumer had
181
+ // individually disabled beforehand.
182
+ private _groupDisabledEls = new WeakSet<HTMLElement>();
183
+
122
184
  constructor() {
123
185
  super();
124
186
  this.variant = 'horizontal';
@@ -126,14 +188,93 @@ export class BdsFieldGroup extends LitElement {
126
188
  this.disabled = false;
127
189
  }
128
190
 
129
- // Arrow-bound for stable identity (unused here but matches the
130
- // bds-popover / bds-button conventions for handlers attached in render).
191
+ connectedCallback() {
192
+ super.connectedCallback();
193
+ // disconnectedCallback tears the observer down; firstUpdated() only
194
+ // fires once per element instance, so a reconnect (e.g. the element was
195
+ // moved in the DOM) needs its own re-arm. No-op on first connect — the
196
+ // shadow root hasn't rendered yet, so _setupObserver finds no elements
197
+ // and firstUpdated() performs the initial setup once it has.
198
+ if (this.hasUpdated) this._setupObserver();
199
+ }
200
+
201
+ disconnectedCallback() {
202
+ super.disconnectedCallback();
203
+ this._ro?.disconnect();
204
+ this._ro = undefined;
205
+ }
206
+
207
+ firstUpdated() {
208
+ this._fieldsetEl = this.renderRoot.querySelector('fieldset') ?? undefined;
209
+ this._probeEl = this.renderRoot.querySelector<HTMLElement>('.probe') ?? undefined;
210
+ this._setupObserver();
211
+ }
212
+
213
+ updated(changed: Map<string, unknown>) {
214
+ super.updated(changed);
215
+ if (changed.has('variant')) {
216
+ this._updateCollapsed();
217
+ }
218
+ if (changed.has('disabled')) {
219
+ this._syncDisabledToSlotted();
220
+ }
221
+ }
222
+
223
+ private _setupObserver() {
224
+ if (this._ro || typeof ResizeObserver === 'undefined') return;
225
+ if (!this._fieldsetEl || !this._probeEl) return;
226
+ this._ro = new ResizeObserver(this._onResize);
227
+ this._ro.observe(this._fieldsetEl);
228
+ this._ro.observe(this._probeEl);
229
+ }
230
+
231
+ // Arrow-bound for stable identity across connect/disconnect cycles.
232
+ private _onResize = (entries: ResizeObserverEntry[]) => {
233
+ for (const entry of entries) {
234
+ const size = entry.contentBoxSize?.[0]?.inlineSize ?? entry.contentRect.width;
235
+ if (entry.target === this._fieldsetEl) this._fieldsetSize = size;
236
+ else if (entry.target === this._probeEl) this._thresholdSize = size;
237
+ }
238
+ this._updateCollapsed();
239
+ };
240
+
241
+ private _updateCollapsed() {
242
+ const shouldCollapse =
243
+ this.variant === 'horizontal' && this._fieldsetSize < this._thresholdSize;
244
+ this.toggleAttribute('data-collapsed', shouldCollapse);
245
+ }
246
+
247
+ // Arrow-bound for stable identity, matching the bds-popover/bds-button
248
+ // convention for handlers attached in render.
131
249
  private _onSlotChange = (e: Event) => {
132
250
  const slot = e.target as HTMLSlotElement;
133
251
  const count = slot.assignedElements().length;
134
252
  this.style.setProperty('--fieldGroup_field-count', String(count));
253
+ this._syncDisabledToSlotted();
135
254
  };
136
255
 
256
+ // Propagates `disabled` to each directly-slotted form control. Only
257
+ // touches controls this instance disabled itself (tracked in
258
+ // _groupDisabledEls) when re-enabling, so a control the consumer
259
+ // individually disabled stays disabled after the group re-enables.
260
+ private _syncDisabledToSlotted() {
261
+ const slot = this.renderRoot.querySelector('slot');
262
+ if (!slot) return;
263
+ for (const el of slot.assignedElements({ flatten: true })) {
264
+ if (!('disabled' in el)) continue;
265
+ const field = el as HTMLElement & { disabled: boolean };
266
+ if (this.disabled) {
267
+ if (!field.disabled) {
268
+ field.disabled = true;
269
+ this._groupDisabledEls.add(field);
270
+ }
271
+ } else if (this._groupDisabledEls.has(field)) {
272
+ field.disabled = false;
273
+ this._groupDisabledEls.delete(field);
274
+ }
275
+ }
276
+ }
277
+
137
278
  render() {
138
279
  return html`
139
280
  <fieldset ?disabled=${this.disabled}>
@@ -143,6 +284,9 @@ export class BdsFieldGroup extends LitElement {
143
284
  <div class="fields">
144
285
  <slot @slotchange=${this._onSlotChange}></slot>
145
286
  </div>
287
+ <div class="probeContainer">
288
+ <div class="probe"></div>
289
+ </div>
146
290
  </fieldset>
147
291
  `;
148
292
  }