@boostdev/design-system-components 2.7.1 → 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 (535) 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-3AY2YKCM.js +223 -0
  15. package/dist/web-components/chunk-3WAV6MDN.js +212 -0
  16. package/dist/web-components/{chunk-CZBIVR4V.js → chunk-47AT5KZD.js} +88 -16
  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-5R6IFELV.js → chunk-AIBOHNDU.js} +11 -1
  23. package/dist/web-components/{chunk-ITHLKR7Q.js → chunk-AP4RDUL2.js} +16 -5
  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-CM3KYZ6Z.js → chunk-JH6LQKLK.js} +78 -6
  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-57TRNCWQ.js → chunk-WFVKU4GX.js} +22 -11
  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-F5E3IT7G.js → chunk-XIZWAWMJ.js} +50 -11
  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 +60 -13
  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 +102 -17
  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 +136 -23
  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 +96 -8
  441. package/src/web-components/interaction/form/bds-slider.spec.ts +83 -0
  442. package/src/web-components/interaction/form/bds-slider.ts +181 -33
  443. package/src/web-components/interaction/form/bds-switch.spec.ts +68 -0
  444. package/src/web-components/interaction/form/bds-switch.ts +142 -41
  445. package/src/web-components/interaction/form/bds-textarea.spec.ts +71 -0
  446. package/src/web-components/interaction/form/bds-textarea.ts +109 -8
  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 +30 -12
  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 +113 -36
  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 +16 -15
  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 +11 -1
  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 +19 -6
  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-5TFWOPLH.js +0 -49
  526. package/dist/web-components/chunk-7FMR53BW.js +0 -127
  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-IYGF6CD5.js +0 -118
  530. package/dist/web-components/chunk-QBB6ZX4R.js +0 -107
  531. package/dist/web-components/chunk-Y3POAKGS.js +0 -133
  532. package/dist/web-components/chunk-Y4MAXTMA.js +0 -80
  533. package/dist/web-components/chunk-Y7V7LM6R.js +0 -98
  534. package/src/web-components/ui/BdsButtonGroup.mdx +0 -69
  535. package/src/web-components/ui/BdsButtonGroup.stories.tsx +0 -66
@@ -4,6 +4,12 @@ import type { GridItemSpanValue } from '../../components/layout/Grid/GridItem';
4
4
 
5
5
  export type GridVariant = 'main' | 'page' | 'funnel' | 'custom';
6
6
 
7
+ // Mirrors masonry.ts's useMasonry hook: RO-triggered resizes of already-laid-out
8
+ // items are deferred while the user is actively scrolling, and applied once
9
+ // scroll idles for this long — avoids a compositor race where a re-pack mid-
10
+ // scroll paints over already-visible content for a frame or two.
11
+ const MASONRY_SCROLL_IDLE_MS = 150;
12
+
7
13
  /**
8
14
  * `<bds-grid>` — framework-agnostic Grid layout custom element.
9
15
  *
@@ -23,16 +29,36 @@ export type GridVariant = 'main' | 'page' | 'funnel' | 'custom';
23
29
  * across breakpoints via the foundation's responsive column
24
30
  * tokens. An item at row-end is demoted to the remaining
25
31
  * column count. Numeric values are literal and don't adapt.
32
+ * masonry-row-unit-px — number; masonry only. Manual override for the
33
+ * row-track unit (px) the polyfill uses for
34
+ * `grid-auto-rows` and as the ceil() granularity of each
35
+ * item's row span. Omit to let the polyfill auto-pick the
36
+ * smallest unit that keeps the implicit row count under
37
+ * any browser cap.
26
38
  *
27
39
  * Slots:
28
40
  * (default) — grid content; typically `<bds-grid-item>` children
29
41
  */
30
42
  export class BdsGrid extends LitElement {
31
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
+
32
54
  :host {
33
55
  display: block;
34
56
  }
35
57
 
58
+ :host([variant='page']) {
59
+ grid-column: 1 / -1;
60
+ }
61
+
36
62
  .grid {
37
63
  display: grid;
38
64
  gap: var(--grid_gap, var(--bds-grid_gap));
@@ -45,7 +71,6 @@ export class BdsGrid extends LitElement {
45
71
 
46
72
  .grid.--page {
47
73
  grid-template-columns: 1fr;
48
- grid-column: 1 / -1;
49
74
  }
50
75
 
51
76
  .grid.--funnel {
@@ -88,6 +113,7 @@ export class BdsGrid extends LitElement {
88
113
  attribute: 'masonry-preferred-column-span',
89
114
  reflect: true,
90
115
  },
116
+ masonryRowUnitPx: { type: Number, attribute: 'masonry-row-unit-px', reflect: true },
91
117
  };
92
118
 
93
119
  declare variant: GridVariant;
@@ -96,10 +122,53 @@ export class BdsGrid extends LitElement {
96
122
  declare isMasonry: boolean;
97
123
  declare autoSpanMedia: boolean;
98
124
  declare masonryPreferredColumnSpan: string | undefined;
125
+ declare masonryRowUnitPx: number | undefined;
99
126
 
100
127
  private _ro?: ResizeObserver;
101
128
  private _mo?: MutationObserver;
102
129
  private _frame = 0;
130
+ // Tracks whether the masonry observers/listeners are currently wired up.
131
+ // Guards _teardownMasonry so a grid that never engaged masonry (or already
132
+ // tore it down) never clears spans it didn't apply.
133
+ private _engaged = false;
134
+ private _scrolling = false;
135
+ private _pendingResize = false;
136
+ private _scrollTimer?: ReturnType<typeof setTimeout>;
137
+
138
+ // RO-triggered re-runs (an already-laid-out item resizing — image decode, font
139
+ // swap) apply immediately unless the user is actively scrolling, in which case
140
+ // they're deferred until scroll idles (see _onScroll) to avoid a compositor
141
+ // race where `grid-auto-flow: dense` re-packs items mid-scroll. Stable
142
+ // arrow-function references so connectedCallback/disconnectedCallback can
143
+ // add/remove the same listener.
144
+ private _onResize = () => {
145
+ if (this._scrolling) {
146
+ this._pendingResize = true;
147
+ return;
148
+ }
149
+ this._apply();
150
+ };
151
+
152
+ // MutationObserver fires when children are added/removed. Newly-added children
153
+ // (and their media descendants) need to be observed for size, and the run is
154
+ // deferred to rAF so the browser lays out the new children before measuring.
155
+ private _onMutate = () => {
156
+ for (const child of this._items()) this._observeDescendants(child);
157
+ this._scheduleMasonry();
158
+ };
159
+
160
+ private _onScroll = () => {
161
+ this._scrolling = true;
162
+ if (this._scrollTimer !== undefined) clearTimeout(this._scrollTimer);
163
+ this._scrollTimer = setTimeout(() => {
164
+ this._scrolling = false;
165
+ this._scrollTimer = undefined;
166
+ if (this._pendingResize) {
167
+ this._pendingResize = false;
168
+ this._apply();
169
+ }
170
+ }, MASONRY_SCROLL_IDLE_MS);
171
+ };
103
172
 
104
173
  constructor() {
105
174
  super();
@@ -109,6 +178,21 @@ export class BdsGrid extends LitElement {
109
178
  this.isMasonry = false;
110
179
  this.autoSpanMedia = false;
111
180
  this.masonryPreferredColumnSpan = undefined;
181
+ this.masonryRowUnitPx = undefined;
182
+ }
183
+
184
+ connectedCallback() {
185
+ super.connectedCallback();
186
+ // Re-arm masonry on reconnect (e.g. the element was moved in the DOM).
187
+ // disconnectedCallback tore down observers/listeners; updated() only fires
188
+ // again on a property change, so a reconnect with no property change would
189
+ // otherwise leave masonry permanently disengaged. No-op on first connect —
190
+ // the shadow root hasn't rendered yet, so _setupMasonry finds no container
191
+ // and updated() performs the initial setup once it has.
192
+ if (this.isMasonry && !supportsNativeMasonry() && !this._engaged) {
193
+ this._setupMasonry();
194
+ this._scheduleMasonry();
195
+ }
112
196
  }
113
197
 
114
198
  disconnectedCallback() {
@@ -121,6 +205,7 @@ export class BdsGrid extends LitElement {
121
205
  this._setupMasonry();
122
206
  this._scheduleMasonry();
123
207
  } else {
208
+ // No-op when masonry was never engaged — see the guard in _teardownMasonry.
124
209
  this._teardownMasonry();
125
210
  }
126
211
  }
@@ -133,37 +218,54 @@ export class BdsGrid extends LitElement {
133
218
  return (Array.from(this.children) as HTMLElement[]).filter((el) => el.nodeType === 1);
134
219
  }
135
220
 
221
+ private _observeDescendants(child: Element) {
222
+ if (!this._ro) return;
223
+ this._ro.observe(child);
224
+ // Also observe media descendants directly. `loading="lazy"` images decode
225
+ // asynchronously; observing the image itself means the polyfill re-runs in
226
+ // the same frame as the decode instead of one frame late.
227
+ for (const media of Array.from(child.querySelectorAll('img, video'))) {
228
+ this._ro.observe(media);
229
+ }
230
+ }
231
+
136
232
  private _setupMasonry() {
137
- if (this._ro || this._mo) return;
233
+ if (this._engaged) return;
138
234
  const container = this._gridEl();
139
235
  if (!container) return;
236
+ this._engaged = true;
140
237
 
141
238
  if (typeof ResizeObserver !== 'undefined') {
142
- this._ro = new ResizeObserver(() => this._scheduleMasonry());
143
- // Only observe children, not the container — container block-size changes when
144
- // we apply row-spans, which would loop back through the observer.
145
- for (const child of this._items()) this._ro.observe(child);
239
+ this._ro = new ResizeObserver(this._onResize);
240
+ // Only observe children (and their media), not the container — container
241
+ // block-size changes when we apply row-spans, which would loop back
242
+ // through the observer.
243
+ for (const child of this._items()) this._observeDescendants(child);
146
244
  }
147
245
 
148
246
  if (typeof MutationObserver !== 'undefined') {
149
- this._mo = new MutationObserver(() => {
150
- if (this._ro) for (const child of this._items()) this._ro.observe(child);
151
- this._scheduleMasonry();
152
- });
247
+ this._mo = new MutationObserver(this._onMutate);
153
248
  this._mo.observe(this, { childList: true });
154
249
  }
250
+
251
+ // `capture: true` catches scroll events from any nested scroll container,
252
+ // since scroll doesn't bubble. `passive: true` tells the browser we won't
253
+ // preventDefault — critical for not blocking scroll performance.
254
+ window.addEventListener('scroll', this._onScroll, { passive: true, capture: true });
255
+ }
256
+
257
+ private _apply() {
258
+ const container = this._gridEl();
259
+ if (!container) return;
260
+ applyMasonryLayout(container, this._items(), {
261
+ preferredColumnSpan: this._resolvePreferredColumnSpan(),
262
+ rowUnitPx: this.masonryRowUnitPx,
263
+ });
155
264
  }
156
265
 
157
266
  private _scheduleMasonry() {
158
267
  cancelAnimationFrame(this._frame);
159
- this._frame = requestAnimationFrame(() => {
160
- const container = this._gridEl();
161
- if (container) {
162
- applyMasonryLayout(container, this._items(), {
163
- preferredColumnSpan: this._resolvePreferredColumnSpan(),
164
- });
165
- }
166
- });
268
+ this._frame = requestAnimationFrame(() => this._apply());
167
269
  }
168
270
 
169
271
  private _resolvePreferredColumnSpan(): Exclude<GridItemSpanValue, 'auto'> | undefined {
@@ -176,11 +278,24 @@ export class BdsGrid extends LitElement {
176
278
  }
177
279
 
178
280
  private _teardownMasonry() {
281
+ // Nothing was ever wired up — skip clearMasonryLayout too, so a non-masonry
282
+ // (or not-yet-engaged) grid never has its slotted items' inline styles
283
+ // (e.g. a `row-span` a consumer set) reset on disconnect/reconnect.
284
+ if (!this._engaged) return;
285
+
179
286
  cancelAnimationFrame(this._frame);
287
+ if (this._scrollTimer !== undefined) {
288
+ clearTimeout(this._scrollTimer);
289
+ this._scrollTimer = undefined;
290
+ }
291
+ this._scrolling = false;
292
+ this._pendingResize = false;
293
+ window.removeEventListener('scroll', this._onScroll, { capture: true } as EventListenerOptions);
180
294
  this._ro?.disconnect();
181
295
  this._mo?.disconnect();
182
296
  this._ro = undefined;
183
297
  this._mo = undefined;
298
+ this._engaged = false;
184
299
  const container = this._gridEl();
185
300
  if (container) clearMasonryLayout(container, this._items());
186
301
  }
@@ -193,8 +308,13 @@ export class BdsGrid extends LitElement {
193
308
  this.isMasonry ? '--masonry' : '',
194
309
  ].filter(Boolean).join(' ');
195
310
 
311
+ // Lit's Number converter yields `null` (not `undefined`) when a reflected
312
+ // attribute is removed — a strict `!== undefined` check would still match
313
+ // and emit the literal string "null", making `var(--grid_columns, 4)`
314
+ // resolve to an invalid custom property and collapse the grid to one
315
+ // column. Loose `!= null` catches both null and undefined.
196
316
  const styleAttr =
197
- this.variant === 'custom' && this.columns !== undefined
317
+ this.variant === 'custom' && this.columns != null
198
318
  ? `--grid_columns: ${this.columns}`
199
319
  : '';
200
320
 
@@ -5,7 +5,7 @@ import * as Stories from './BdsAlert.stories';
5
5
 
6
6
  # &lt;bds-alert&gt;
7
7
 
8
- Framework-agnostic alert custom element for inline status messages. Supports four semantic variants, an optional title, and a dismissible mode.
8
+ Framework-agnostic alert custom element for inline status messages. Supports four semantic variants, an optional heading, and a dismissible mode.
9
9
 
10
10
  > **Status: experimental** — API may change before stable release.
11
11
 
@@ -32,8 +32,8 @@ import '@boostdev/design-system-components/web-components';
32
32
  ### Error
33
33
  <Canvas of={Stories.Error} />
34
34
 
35
- ### With title
36
- <Canvas of={Stories.WithTitle} />
35
+ ### With heading
36
+ <Canvas of={Stories.WithHeading} />
37
37
 
38
38
  ### Dismissible
39
39
  <Canvas of={Stories.Dismissible} />
@@ -47,7 +47,8 @@ import '@boostdev/design-system-components/web-components';
47
47
  | Attribute | Type | Default | Description |
48
48
  |-----------|------|---------|-------------|
49
49
  | `variant` | `"info" \| "success" \| "warning" \| "error"` | `"info"` | Semantic colour and icon |
50
- | `title` | string | — | Optional heading displayed above body content |
50
+ | `heading` | string | — | Optional heading displayed above body content |
51
+ | `title` | string | — | **Deprecated.** Alias for `heading`, used as a fallback when `heading` is unset. Avoid: it shares its name with the global HTML `title` attribute, which makes the browser show a native tooltip on hover. Will be removed in a later major — use `heading` instead. |
51
52
  | `dismissible` | boolean | `false` | Shows a dismiss (×) button |
52
53
 
53
54
  ## Slots
@@ -66,7 +67,7 @@ import '@boostdev/design-system-components/web-components';
66
67
  ## Usage in plain HTML
67
68
 
68
69
  ```html
69
- <bds-alert variant="success" title="Saved">
70
+ <bds-alert variant="success" heading="Saved">
70
71
  Your changes have been saved successfully.
71
72
  </bds-alert>
72
73
 
@@ -6,20 +6,20 @@ import '../index'; // auto-registers all custom elements
6
6
  // Thin React wrapper so Storybook controls work with the custom element's props
7
7
  function BdsAlert({
8
8
  variant = 'info',
9
- title,
9
+ heading,
10
10
  dismissible,
11
11
  children,
12
12
  onDismiss,
13
13
  }: {
14
14
  variant?: AlertVariant;
15
- title?: string;
15
+ heading?: string;
16
16
  dismissible?: boolean;
17
17
  children?: React.ReactNode;
18
18
  onDismiss?: () => void;
19
19
  }) {
20
20
  return React.createElement(
21
21
  'bds-alert',
22
- { variant, title, dismissible: dismissible || undefined, onbdsdismiss: onDismiss },
22
+ { variant, heading, dismissible: dismissible || undefined, onbdsdismiss: onDismiss },
23
23
  children,
24
24
  );
25
25
  }
@@ -41,8 +41,8 @@ export const Info: Story = { args: { children: 'This is an informational message
41
41
  export const Success: Story = { args: { children: 'Your changes have been saved.', variant: 'success' } };
42
42
  export const Warning: Story = { args: { children: 'Please review before continuing.', variant: 'warning' } };
43
43
  export const Error: Story = { args: { children: 'Something went wrong.', variant: 'error' } };
44
- export const WithTitle: Story = {
45
- args: { children: 'More details about the alert.', variant: 'info', title: 'Heads up' },
44
+ export const WithHeading: Story = {
45
+ args: { children: 'More details about the alert.', variant: 'info', heading: 'Heads up' },
46
46
  };
47
47
  export const Dismissible: Story = {
48
48
  args: { children: 'You can dismiss this alert.', variant: 'success', dismissible: true },
@@ -51,7 +51,7 @@ export const AllVariants: Story = {
51
51
  render: () => (
52
52
  <div style={{ display: 'flex', flexDirection: 'column', gap: '12px', maxWidth: 500 }}>
53
53
  {(['info', 'success', 'warning', 'error'] as const).map(v => (
54
- <BdsAlert key={v} variant={v} title={v.charAt(0).toUpperCase() + v.slice(1)}>
54
+ <BdsAlert key={v} variant={v} heading={v.charAt(0).toUpperCase() + v.slice(1)}>
55
55
  This is a {v} alert.
56
56
  </BdsAlert>
57
57
  ))}
@@ -46,7 +46,7 @@ import '@boostdev/design-system-components/web-components';
46
46
  | Attribute | Type | Default | Description |
47
47
  |-----------|------|---------|-------------|
48
48
  | `src` | string | — | Photo URL; when set the image is shown |
49
- | `alt` | string | `name` or `"User avatar"` | Alt text for the `<img>` element |
49
+ | `alt` | string | `name` or `"User avatar"` | Alt text for the `<img>` element. Pass `alt=""` explicitly to mark a decorative image — an empty attribute is preserved as-is and is not replaced by `name`/`"User avatar"`. |
50
50
  | `name` | string | — | Full name; used to compute up to two initials and as `aria-label` |
51
51
  | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Diameter scale |
52
52
 
@@ -54,6 +54,8 @@ import '@boostdev/design-system-components/web-components';
54
54
 
55
55
  | Property | Description |
56
56
  |----------|-------------|
57
+ | `--avatar_size` | Diameter override (wins over the `size` attribute's preset); defaults to `3em` |
58
+ | `--avatar_radius` | Corner radius; defaults to `var(--bds-border_radius--circle)` |
57
59
  | `--avatar_bg` | Background colour of the fallback initials circle |
58
60
  | `--avatar_text` | Text colour of the initials |
59
61
 
@@ -73,4 +75,4 @@ import '@boostdev/design-system-components/web-components';
73
75
  ## Accessibility
74
76
 
75
77
  - Without `src`: renders `role="img"` with `aria-label` set to `name` (or "User avatar")
76
- - With `src`: renders `<img>` with `alt` set to `alt`, `name`, or "User avatar"
78
+ - With `src`: renders `<img>` with `alt` set to the explicit `alt` attribute when provided (including `alt=""` for a decorative image), otherwise falling back to `name`, or "User avatar"
@@ -5,7 +5,7 @@ import * as Stories from './BdsBreadcrumb.stories';
5
5
 
6
6
  # &lt;bds-breadcrumb&gt;
7
7
 
8
- Framework-agnostic Breadcrumb custom element. Renders a horizontal navigation trail from a JSON array of `{ label, href? }` items. The last item is treated as the current page and rendered without a link.
8
+ Framework-agnostic Breadcrumb custom element. Renders a horizontal navigation trail from a JSON array of `{ label, href? }` items. The last item is treated as the current page and rendered without a link. Non-last items without an `href` render as plain (non-interactive) text instead of an unusable link.
9
9
 
10
10
  > **Status: experimental** — API may change before stable release.
11
11
 
@@ -39,7 +39,7 @@ import '@boostdev/design-system-components/web-components';
39
39
 
40
40
  | Attribute | Type | Default | Description |
41
41
  |-----------|------|---------|-------------|
42
- | `items` | `Array<{ label: string; href?: string }>` | `[]` | Breadcrumb items as a JSON-serialisable array. The last item is always the current page. |
42
+ | `items` | `Array<{ label: string; href?: string }>` | `[]` | Breadcrumb items as a JSON-serialisable array. The last item is always the current page. Malformed JSON (or a removed attribute) falls back to an empty list rather than crashing the render. |
43
43
 
44
44
  ## Usage in plain HTML
45
45
 
@@ -64,3 +64,4 @@ document.querySelector('bds-breadcrumb').items = [
64
64
  - Wrapped in `<nav aria-label="Breadcrumb">` with an `<ol>` list structure
65
65
  - The current page item carries `aria-current="page"`
66
66
  - Separator characters are `aria-hidden="true"` to avoid screen reader noise
67
+ - Non-last items without an `href` render as plain text rather than a link with `href="#"` — this avoids an interactive-looking element that scrolls to top and pushes a history entry when activated
@@ -0,0 +1,64 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsButtonContainer.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # &lt;bds-button-container&gt;
7
+
8
+ Framework-agnostic layout wrapper for a row of action buttons (Cancel / Confirm, Back / Next). Web-component port of the React `ButtonContainer`.
9
+
10
+ > **Status: experimental** — API may change before stable release.
11
+
12
+ Buttons stack vertically (primary on top, via `column-reverse`) on narrow containers and lay out in a row once the container is at least `30rem` wide. The `variant` controls alignment: `flow` (multi-step navigation), `card` (single-form submit), `modal` (dialog actions, aligned end), `content` (inline actions, aligned start).
13
+
14
+ ## Installation
15
+
16
+ ```js
17
+ import '@boostdev/design-system-components/web-components';
18
+ ```
19
+
20
+ ## Examples
21
+
22
+ ### Two buttons
23
+ <Canvas of={Stories.TwoButtons} />
24
+
25
+ ### Three buttons
26
+ <Canvas of={Stories.ThreeButtons} />
27
+
28
+ ### Variants
29
+ <Canvas of={Stories.Variants} />
30
+
31
+ ## Props
32
+
33
+ <ArgTypes of={Stories} />
34
+
35
+ ## Attributes
36
+
37
+ | Attribute | Type | Default | Description |
38
+ |-----------|------|---------|-------------|
39
+ | `variant` | `"flow" \| "card" \| "modal" \| "content"` | — | Alignment of the button row |
40
+ | `aria-label` | string | — | Accessible label for the group container |
41
+
42
+ ## Slots
43
+
44
+ | Slot | Description |
45
+ |------|-------------|
46
+ | `(default)` | `<bds-button>` elements |
47
+
48
+ ## Usage in plain HTML
49
+
50
+ ```html
51
+ <bds-button-container variant="modal" aria-label="Dialog actions">
52
+ <bds-button variant="outline">Cancel</bds-button>
53
+ <bds-button>Confirm</bds-button>
54
+ </bds-button-container>
55
+ ```
56
+
57
+ ## Deprecated: `<bds-button-group>`
58
+
59
+ `<bds-button-group>` is a **deprecated alias** of `<bds-button-container>` and behaves identically. Migrate to `<bds-button-container>`; the alias (and its `./web-components/ui/bds-button-group` deep import) will be removed in a future major version.
60
+
61
+ ## Accessibility
62
+
63
+ - Renders a `<div role="group">` with the provided `aria-label`; the attribute is omitted entirely (not an empty string) when unset
64
+ - Always set `aria-label` to describe the purpose of the group
@@ -0,0 +1,84 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import type { ButtonContainerVariant } from './bds-button-container';
4
+ import '../index'; // auto-registers all custom elements
5
+
6
+ function BdsButtonContainer({
7
+ variant,
8
+ ariaLabel,
9
+ children,
10
+ }: {
11
+ variant?: ButtonContainerVariant;
12
+ ariaLabel?: string;
13
+ children?: React.ReactNode;
14
+ }) {
15
+ return React.createElement('bds-button-container', { variant, 'aria-label': ariaLabel }, children);
16
+ }
17
+
18
+ const meta = {
19
+ title: 'Web Components/Layout/ButtonContainer',
20
+ component: BdsButtonContainer,
21
+ tags: ['!stable', 'experimental'],
22
+ parameters: { layout: 'padded' },
23
+ argTypes: {
24
+ variant: { control: 'radio', options: ['flow', 'card', 'modal', 'content'] },
25
+ ariaLabel: { control: 'text' },
26
+ },
27
+ } satisfies Meta<typeof BdsButtonContainer>;
28
+
29
+ export default meta;
30
+ type Story = StoryObj<typeof meta>;
31
+
32
+ const btn = (label: string, variant?: string) =>
33
+ React.createElement('bds-button', variant ? { variant } : null, label);
34
+
35
+ /** Two actions — the common Cancel / Confirm dialog row. */
36
+ export const TwoButtons: Story = {
37
+ render: () =>
38
+ React.createElement(
39
+ 'bds-button-container',
40
+ { variant: 'modal', 'aria-label': 'Dialog actions' },
41
+ btn('Cancel', 'outline'),
42
+ btn('Confirm'),
43
+ ),
44
+ };
45
+
46
+ /** Three actions. */
47
+ export const ThreeButtons: Story = {
48
+ render: () =>
49
+ React.createElement(
50
+ 'bds-button-container',
51
+ { variant: 'content', 'aria-label': 'Actions' },
52
+ btn('Back', 'outline'),
53
+ btn('Save draft', 'outline'),
54
+ btn('Publish'),
55
+ ),
56
+ };
57
+
58
+ /** All four alignment variants (resize the viewport to see the row/stack switch at 30rem). */
59
+ export const Variants: Story = {
60
+ render: () =>
61
+ React.createElement(
62
+ 'div',
63
+ { style: { display: 'flex', flexDirection: 'column', gap: '2rem' } },
64
+ ...(['flow', 'card', 'modal', 'content'] as const).map((v) =>
65
+ React.createElement(
66
+ 'bds-button-container',
67
+ { key: v, variant: v, 'aria-label': v },
68
+ btn('Cancel', 'outline'),
69
+ btn('Confirm'),
70
+ ),
71
+ ),
72
+ ),
73
+ };
74
+
75
+ /** `<bds-button-group>` is a deprecated alias and behaves identically — prefer `<bds-button-container>`. */
76
+ export const DeprecatedButtonGroupAlias: Story = {
77
+ render: () =>
78
+ React.createElement(
79
+ 'bds-button-group',
80
+ { variant: 'modal', 'aria-label': 'Legacy alias' },
81
+ btn('Cancel', 'outline'),
82
+ btn('Confirm'),
83
+ ),
84
+ };
@@ -50,6 +50,11 @@ import '@boostdev/design-system-components/web-components';
50
50
  | `min` | string | — | Minimum selectable date (ISO 8601) |
51
51
  | `max` | string | — | Maximum selectable date (ISO 8601) |
52
52
  | `disabled` | boolean | `false` | Disables all interaction |
53
+ | `months` | number | `1` | Number of months shown side by side |
54
+ | `page-by` | `"months"` \| `"single"` | `"months"` | Pagination step |
55
+ | `first-day-of-week` | number (0–6) | `1` | First weekday column (Monday) |
56
+ | `locale` | string | runtime default | `Intl` locale for date text |
57
+ | `previous-label` / `next-label` | string | English | Nav button aria-labels |
53
58
 
54
59
  ## Events
55
60
 
@@ -57,6 +62,23 @@ import '@boostdev/design-system-components/web-components';
57
62
  |-------|--------|-------------|
58
63
  | `bds-date-select` | `{ date: string }` | Fired when the user selects a date; `date` is in `YYYY-MM-DD` format |
59
64
 
65
+ ## CSS Custom Properties
66
+
67
+ | Property | Description |
68
+ |----------|--------------|
69
+ | `--calendar_border` | Border on the calendar frame (default: `none`) |
70
+ | `--calendar_radius` | Corner radius of the calendar frame (default: `var(--bds-border_radius--m)`) |
71
+ | `--calendar_shadow` | Elevation shadow on the calendar frame (default: `var(--bds-shadow_s)`) |
72
+ | `--calendar_button-radius` | Corner radius shared by the nav buttons and day buttons (default: `var(--bds-border_radius--circle)`) |
73
+ | `--calendar_navBtn-bg--hover` | Nav button background on hover (default: `var(--bds-color_bg--subtle)`) |
74
+ | `--calendar_day-bg--hover` | Day background on hover (default: `var(--bds-color_bg--subtle)`) |
75
+ | `--calendar_today-color` | Colour of today's ring (default: `var(--bds-color_interactive)`) |
76
+ | `--calendar_today-border` | Border used for today's ring (default: `none`) |
77
+ | `--calendar_today-shadow` | Shadow tail appended after today's inset ring (default: `var(--bdc-outline_shadow)`) |
78
+ | `--calendar_day-bg--selected` | Selected day background (default: `var(--bds-color_interactive)`) |
79
+ | `--calendar_day-color--selected` | Selected day text colour (default: `var(--bds-color_on-interactive)`) |
80
+ | `--calendar_day-bg--in-range` | Background of days between the range endpoints (default: `var(--bds-color_blue--subtle)`) |
81
+
60
82
  ## Usage in plain HTML
61
83
 
62
84
  ```html
@@ -82,12 +104,15 @@ import '@boostdev/design-system-components/web-components';
82
104
  | End | Move to end of week |
83
105
  | Page Up | Navigate to previous month |
84
106
  | Page Down | Navigate to next month |
107
+ | Shift + Page Up / Down | Previous / next year |
85
108
  | Enter / Space | Select focused date |
86
109
 
87
110
  ## Accessibility
88
111
 
89
- - Uses the ARIA grid pattern with `role="grid"` and `role="gridcell"` on day buttons
112
+ - Uses the full ARIA grid pattern: `role="grid"` on the grid container, `role="row"` wrapping the column-header row and each week, `role="columnheader"` on weekday labels, and `role="gridcell"` on a wrapper element around each day `<button>`
113
+ - Uses roving tabindex — exactly one day button is ever part of the Tab order at a time (`tabindex="0"`; every other day is `tabindex="-1"`). It prefers, in order: the day currently focused via arrow-key navigation, the selected date (if visible in the current month), today (if visible), then the 1st of the visible month — so the grid never loses its only tab stop after navigating to a month with neither the selected date nor today in view
90
114
  - The month/year label uses `aria-live="polite"` for screen reader announcements on navigation
91
- - Each day carries `aria-selected` and `aria-current="date"` (today)
92
- - Disabled days carry `aria-disabled="true"` and are not focusable
93
- - Respects the `disabled` attribute at the host level
115
+ - The `role="gridcell"` wrapper carries `aria-selected`; the day `<button>` carries `aria-current="date"` on today (non-today days omit `aria-current` entirely rather than emitting `aria-current="false"`) and `aria-disabled`. Days outside the current month are inert — greyed, non-selectable, and never marked selected/current
116
+ - Disabled days carry `aria-disabled="true"` and are not focusable (native `disabled` button)
117
+ - Respects the `disabled` attribute at the host level — disables day selection, keyboard navigation, and the month nav buttons; also responds to `formDisabledCallback` (e.g. an ancestor `<fieldset disabled>`)
118
+ - Respects `prefers-reduced-motion` — day and nav-button transitions are disabled for users who request reduced motion
@@ -3,24 +3,17 @@ import type { Meta, StoryObj } from '@storybook/react';
3
3
  import '../index'; // auto-registers all custom elements
4
4
 
5
5
  function BdsCalendar({
6
- name,
7
- value,
8
- min,
9
- max,
10
- disabled,
6
+ name, value, min, max, disabled, months, firstDayOfWeek, locale,
11
7
  }: {
12
- name?: string;
13
- value?: string;
14
- min?: string;
15
- max?: string;
16
- disabled?: boolean;
8
+ name?: string; value?: string; min?: string; max?: string; disabled?: boolean;
9
+ months?: number; firstDayOfWeek?: number; locale?: string;
17
10
  }) {
18
11
  return React.createElement('bds-calendar', {
19
- name,
20
- value,
21
- min,
22
- max,
12
+ name, value, min, max,
23
13
  disabled: disabled || undefined,
14
+ months,
15
+ 'first-day-of-week': firstDayOfWeek,
16
+ locale,
24
17
  });
25
18
  }
26
19
 
@@ -30,10 +23,13 @@ const meta = {
30
23
  tags: ['!stable', 'experimental'],
31
24
  parameters: { layout: 'centered' },
32
25
  argTypes: {
33
- value: { control: 'text' },
34
- min: { control: 'text' },
35
- max: { control: 'text' },
36
- disabled: { control: 'boolean' },
26
+ value: { control: 'text' },
27
+ min: { control: 'text' },
28
+ max: { control: 'text' },
29
+ disabled: { control: 'boolean' },
30
+ months: { control: 'number' },
31
+ firstDayOfWeek: { control: 'number' },
32
+ locale: { control: 'text' },
37
33
  },
38
34
  } satisfies Meta<typeof BdsCalendar>;
39
35
 
@@ -46,6 +42,8 @@ export const WithMinMax: Story = {
46
42
  args: { value: '2026-04-10', min: '2026-04-05', max: '2026-04-25' },
47
43
  };
48
44
  export const Disabled: Story = { args: { value: '2026-04-10', disabled: true } };
45
+ export const TwoMonths: Story = { args: { value: '2026-04-15', months: 2 } };
46
+ export const DutchLocale: Story = { args: { value: '2026-04-15', locale: 'nl-NL', firstDayOfWeek: 1 } };
49
47
  export const FormField: Story = {
50
48
  render: () => (
51
49
  <form