@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.
- package/AGENTS.md +54 -46
- package/README.md +34 -20
- package/dist/client.cjs +1317 -779
- package/dist/client.css +1029 -812
- package/dist/client.d.cts +88 -26
- package/dist/client.d.ts +88 -26
- package/dist/client.js +1278 -732
- package/dist/index.cjs +1317 -779
- package/dist/index.css +1029 -812
- package/dist/index.d.cts +88 -26
- package/dist/index.d.ts +88 -26
- package/dist/index.js +1278 -732
- package/dist/web-components/chunk-2OLVQUBU.js +193 -0
- package/dist/web-components/chunk-3AY2YKCM.js +223 -0
- package/dist/web-components/chunk-3WAV6MDN.js +212 -0
- package/dist/web-components/{chunk-CZBIVR4V.js → chunk-47AT5KZD.js} +88 -16
- package/dist/web-components/chunk-4A2YYTYN.js +93 -0
- package/dist/web-components/{chunk-Q4T5BJT6.js → chunk-62NK3ZSC.js} +18 -3
- package/dist/web-components/chunk-66M6ETWD.js +77 -0
- package/dist/web-components/{chunk-NCPQ7AF3.js → chunk-6G22I2CK.js} +18 -3
- package/dist/web-components/{chunk-QDST57JC.js → chunk-7ZOJ7N4E.js} +14 -4
- package/dist/web-components/{chunk-5R6IFELV.js → chunk-AIBOHNDU.js} +11 -1
- package/dist/web-components/{chunk-ITHLKR7Q.js → chunk-AP4RDUL2.js} +16 -5
- package/dist/web-components/{chunk-QWPACK5L.js → chunk-BPYKZVDK.js} +11 -1
- package/dist/web-components/{chunk-YLVTEY23.js → chunk-BTCMJQKB.js} +53 -21
- package/dist/web-components/chunk-CUKQ2L5B.js +245 -0
- package/dist/web-components/chunk-DIZDCL7Z.js +14 -0
- package/dist/web-components/{chunk-PC3IOQAH.js → chunk-DV5T43ZC.js} +27 -7
- package/dist/web-components/{chunk-2QA62WCQ.js → chunk-EF7IVYTY.js} +10 -0
- package/dist/web-components/{chunk-L3XHOMN6.js → chunk-F3ZDNHZZ.js} +26 -1
- package/dist/web-components/chunk-FEDABOR5.js +248 -0
- package/dist/web-components/{chunk-6I2DBFQ7.js → chunk-HGFCJXOQ.js} +36 -5
- package/dist/web-components/{chunk-SOQQ7RVJ.js → chunk-IPGHUCJT.js} +23 -8
- package/dist/web-components/chunk-ITD2MV5K.js +392 -0
- package/dist/web-components/{chunk-CM3KYZ6Z.js → chunk-JH6LQKLK.js} +78 -6
- package/dist/web-components/chunk-JMCXAAFK.js +120 -0
- package/dist/web-components/{chunk-KUI55GFB.js → chunk-JUPCZVVW.js} +50 -18
- package/dist/web-components/chunk-JV5QT2OU.js +146 -0
- package/dist/web-components/{chunk-3GFWLSLS.js → chunk-KA3VPKMY.js} +29 -6
- package/dist/web-components/{chunk-CR5PGUHV.js → chunk-KJGRFDFI.js} +26 -11
- package/dist/web-components/{chunk-PY62FTRW.js → chunk-KZPRFY5P.js} +68 -33
- package/dist/web-components/{chunk-X46KL5BK.js → chunk-LDIPCTRN.js} +18 -1
- package/dist/web-components/chunk-M3ECULRH.js +174 -0
- package/dist/web-components/chunk-NBN2ENWJ.js +90 -0
- package/dist/web-components/chunk-NIN3JO6Q.js +189 -0
- package/dist/web-components/{chunk-2FGATTGT.js → chunk-NTQ4TCUT.js} +76 -55
- package/dist/web-components/chunk-OY74D4X6.js +302 -0
- package/dist/web-components/{chunk-3S42DZ7W.js → chunk-P24JYC5V.js} +7 -0
- package/dist/web-components/{chunk-BKIHQYJR.js → chunk-PXPPKCLT.js} +17 -2
- package/dist/web-components/{chunk-TQ7IQ4GZ.js → chunk-QEF2IRID.js} +71 -29
- package/dist/web-components/chunk-QZAIRJ75.js +111 -0
- package/dist/web-components/{chunk-6I3CFC26.js → chunk-RSZ3BWBK.js} +20 -5
- package/dist/web-components/chunk-RVF7W653.js +101 -0
- package/dist/web-components/chunk-SEO2F5KJ.js +234 -0
- package/dist/web-components/{chunk-VMMVWLXL.js → chunk-SFZ6Q4BP.js} +10 -0
- package/dist/web-components/{chunk-LY62SAVN.js → chunk-SYNLFKD3.js} +12 -2
- package/dist/web-components/chunk-TMWXRHGF.js +192 -0
- package/dist/web-components/{chunk-65JXQOBA.js → chunk-U3YZE6R6.js} +51 -7
- package/dist/web-components/chunk-UO7ROSHD.js +424 -0
- package/dist/web-components/chunk-VANAKB6D.js +152 -0
- package/dist/web-components/{chunk-PXZWYO6Z.js → chunk-VED2DFJ6.js} +108 -29
- package/dist/web-components/chunk-W6H5ID2U.js +161 -0
- package/dist/web-components/{chunk-57TRNCWQ.js → chunk-WFVKU4GX.js} +22 -11
- package/dist/web-components/{chunk-OQTRTMAB.js → chunk-WIBAN7KP.js} +10 -0
- package/dist/web-components/chunk-XI7KRAH7.js +54 -0
- package/dist/web-components/{chunk-F5E3IT7G.js → chunk-XIZWAWMJ.js} +50 -11
- package/dist/web-components/{chunk-FXURM6D5.js → chunk-YFAXGRPR.js} +10 -0
- package/dist/web-components/globals.js +1 -1
- package/dist/web-components/index.d.ts +77 -707
- package/dist/web-components/index.js +339 -2066
- package/dist/web-components/interaction/bds-accordion-item.js +1 -1
- package/dist/web-components/interaction/bds-accordion.js +1 -1
- package/dist/web-components/interaction/bds-button.d.ts +10 -2
- package/dist/web-components/interaction/bds-button.js +1 -1
- package/dist/web-components/interaction/bds-collapsible.d.ts +7 -2
- package/dist/web-components/interaction/bds-collapsible.js +1 -1
- package/dist/web-components/interaction/bds-dialog.d.ts +11 -3
- package/dist/web-components/interaction/bds-dialog.js +1 -1
- package/dist/web-components/interaction/bds-drawer.d.ts +7 -1
- package/dist/web-components/interaction/bds-drawer.js +1 -1
- package/dist/web-components/interaction/bds-dropdown-menu-item.d.ts +51 -0
- package/dist/web-components/interaction/bds-dropdown-menu-item.js +7 -0
- package/dist/web-components/interaction/bds-dropdown-menu.d.ts +70 -0
- package/dist/web-components/interaction/bds-dropdown-menu.js +7 -0
- package/dist/web-components/interaction/bds-popover.d.ts +14 -3
- package/dist/web-components/interaction/bds-popover.js +1 -1
- package/dist/web-components/interaction/bds-skip-link.js +1 -1
- package/dist/web-components/interaction/bds-tab-panel.js +1 -1
- package/dist/web-components/interaction/bds-tab.js +1 -1
- package/dist/web-components/interaction/bds-tabs.d.ts +1 -0
- package/dist/web-components/interaction/bds-tabs.js +1 -1
- package/dist/web-components/interaction/bds-toast-provider.js +1 -1
- package/dist/web-components/interaction/bds-tooltip.d.ts +19 -3
- package/dist/web-components/interaction/bds-tooltip.js +1 -1
- package/dist/web-components/interaction/form/bds-checkbox-group.d.ts +83 -0
- package/dist/web-components/interaction/form/bds-checkbox-group.js +7 -0
- package/dist/web-components/interaction/form/bds-checkbox.d.ts +6 -0
- package/dist/web-components/interaction/form/bds-checkbox.js +1 -1
- package/dist/web-components/interaction/form/bds-combobox.d.ts +18 -0
- package/dist/web-components/interaction/form/bds-combobox.js +1 -1
- package/dist/web-components/interaction/form/bds-field-group.d.ts +89 -0
- package/dist/web-components/interaction/form/bds-field-group.js +7 -0
- package/dist/web-components/interaction/form/bds-file-input.d.ts +1 -1
- package/dist/web-components/interaction/form/bds-file-input.js +1 -1
- package/dist/web-components/interaction/form/bds-form-input.d.ts +92 -0
- package/dist/web-components/interaction/form/bds-form-input.js +7 -0
- package/dist/web-components/interaction/form/bds-number-input.d.ts +18 -1
- package/dist/web-components/interaction/form/bds-number-input.js +1 -1
- package/dist/web-components/interaction/form/bds-radio-group.d.ts +81 -0
- package/dist/web-components/interaction/form/bds-radio-group.js +7 -0
- package/dist/web-components/interaction/form/bds-radio.d.ts +34 -6
- package/dist/web-components/interaction/form/bds-radio.js +1 -1
- package/dist/web-components/interaction/form/bds-segmented-control.d.ts +4 -4
- package/dist/web-components/interaction/form/bds-segmented-control.js +1 -1
- package/dist/web-components/interaction/form/bds-select.d.ts +22 -1
- package/dist/web-components/interaction/form/bds-select.js +1 -1
- package/dist/web-components/interaction/form/bds-slider.d.ts +42 -10
- package/dist/web-components/interaction/form/bds-slider.js +1 -1
- package/dist/web-components/interaction/form/bds-switch.d.ts +20 -0
- package/dist/web-components/interaction/form/bds-switch.js +1 -1
- package/dist/web-components/interaction/form/bds-textarea.d.ts +23 -3
- package/dist/web-components/interaction/form/bds-textarea.js +1 -1
- package/dist/web-components/layout/bds-grid-item.d.ts +63 -0
- package/dist/web-components/layout/bds-grid-item.js +7 -0
- package/dist/web-components/layout/bds-grid.d.ts +108 -0
- package/dist/web-components/layout/bds-grid.js +7 -0
- package/dist/web-components/ui/bds-alert.d.ts +16 -2
- package/dist/web-components/ui/bds-alert.js +1 -1
- package/dist/web-components/ui/bds-avatar.d.ts +2 -1
- package/dist/web-components/ui/bds-avatar.js +1 -1
- package/dist/web-components/ui/bds-badge.js +1 -1
- package/dist/web-components/ui/bds-breadcrumb.d.ts +3 -1
- package/dist/web-components/ui/bds-breadcrumb.js +1 -1
- package/dist/web-components/ui/bds-button-container.d.ts +52 -0
- package/dist/web-components/ui/bds-button-container.js +7 -0
- package/dist/web-components/ui/bds-button-group.d.ts +21 -0
- package/dist/web-components/ui/bds-button-group.js +8 -0
- package/dist/web-components/ui/bds-calendar.d.ts +121 -0
- package/dist/web-components/ui/bds-calendar.js +7 -0
- package/dist/web-components/ui/bds-card.d.ts +12 -3
- package/dist/web-components/ui/bds-card.js +1 -1
- package/dist/web-components/ui/bds-carousel.d.ts +98 -0
- package/dist/web-components/ui/bds-carousel.js +7 -0
- package/dist/web-components/ui/bds-description-list.js +1 -1
- package/dist/web-components/ui/bds-icon-wrapper.d.ts +0 -9
- package/dist/web-components/ui/bds-icon-wrapper.js +1 -1
- package/dist/web-components/ui/bds-link.js +1 -1
- package/dist/web-components/ui/bds-loading.js +1 -1
- package/dist/web-components/ui/bds-notification-banner.js +1 -1
- package/dist/web-components/ui/bds-pagination.d.ts +47 -0
- package/dist/web-components/ui/bds-pagination.js +7 -0
- package/dist/web-components/ui/bds-progress-circle.d.ts +3 -1
- package/dist/web-components/ui/bds-progress-circle.js +1 -1
- package/dist/web-components/ui/bds-progress.d.ts +3 -1
- package/dist/web-components/ui/bds-progress.js +1 -1
- package/dist/web-components/ui/bds-rating.js +1 -1
- package/dist/web-components/ui/bds-section-header.d.ts +18 -4
- package/dist/web-components/ui/bds-section-header.js +1 -1
- package/dist/web-components/ui/bds-separator.js +1 -1
- package/dist/web-components/ui/bds-skeleton.js +1 -1
- package/dist/web-components/ui/bds-table.d.ts +52 -0
- package/dist/web-components/ui/bds-table.js +7 -0
- package/dist/web-components/ui/bds-typography.d.ts +1 -0
- package/dist/web-components/ui/bds-typography.js +1 -1
- package/package.json +60 -3
- package/src/components/interaction/Button/Button.module.css +23 -14
- package/src/components/interaction/Button/Button.spec.tsx +20 -0
- package/src/components/interaction/Button/Button.tsx +2 -2
- package/src/components/interaction/Command/Command.mdx +5 -2
- package/src/components/interaction/Command/Command.module.css +23 -7
- package/src/components/interaction/Command/Command.spec.tsx +35 -0
- package/src/components/interaction/Command/Command.tsx +15 -4
- package/src/components/interaction/Command/index.ts +1 -1
- package/src/components/interaction/Dialog/Dialog.mdx +4 -4
- package/src/components/interaction/Dialog/Dialog.module.css +20 -0
- package/src/components/interaction/Dialog/Dialog.spec.tsx +20 -0
- package/src/components/interaction/Dialog/Dialog.tsx +8 -3
- package/src/components/interaction/Dialog/index.ts +1 -0
- package/src/components/interaction/Drawer/Drawer.mdx +5 -2
- package/src/components/interaction/Drawer/Drawer.module.css +34 -3
- package/src/components/interaction/Drawer/Drawer.spec.tsx +67 -1
- package/src/components/interaction/Drawer/Drawer.tsx +30 -12
- package/src/components/interaction/Drawer/index.ts +1 -0
- package/src/components/interaction/DropdownMenu/DropdownMenu.mdx +2 -0
- package/src/components/interaction/DropdownMenu/DropdownMenu.spec.tsx +34 -0
- package/src/components/interaction/DropdownMenu/DropdownMenu.tsx +15 -5
- package/src/components/interaction/DropdownMenu/index.ts +1 -0
- package/src/components/interaction/Popover/Popover.mdx +6 -2
- package/src/components/interaction/Popover/Popover.module.css +26 -18
- package/src/components/interaction/Popover/Popover.spec.tsx +38 -0
- package/src/components/interaction/Popover/Popover.tsx +19 -5
- package/src/components/interaction/Popover/index.ts +1 -0
- package/src/components/interaction/Rating/Rating.mdx +1 -1
- package/src/components/interaction/Rating/Rating.module.css +2 -2
- package/src/components/interaction/Rating/Rating.tsx +1 -1
- package/src/components/interaction/Rating/index.ts +1 -0
- package/src/components/interaction/Toast/Toast.mdx +3 -0
- package/src/components/interaction/Toast/Toast.module.css +35 -5
- package/src/components/interaction/Toast/Toast.spec.tsx +69 -1
- package/src/components/interaction/Toast/Toast.tsx +15 -9
- package/src/components/interaction/form/Checkbox/Checkbox.mdx +3 -0
- package/src/components/interaction/form/Checkbox/Checkbox.module.css +13 -6
- package/src/components/interaction/form/Checkbox/Checkbox.spec.tsx +6 -0
- package/src/components/interaction/form/Checkbox/Checkbox.tsx +1 -1
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.mdx +16 -1
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.module.css +24 -8
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.spec.tsx +32 -2
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.tsx +14 -2
- package/src/components/interaction/form/Combobox/Combobox.mdx +11 -4
- package/src/components/interaction/form/Combobox/Combobox.module.css +6 -6
- package/src/components/interaction/form/Combobox/Combobox.spec.tsx +47 -0
- package/src/components/interaction/form/Combobox/Combobox.tsx +10 -5
- package/src/components/interaction/form/FieldGroup/FieldGroup.mdx +9 -10
- package/src/components/interaction/form/FieldGroup/FieldGroup.module.css +57 -23
- package/src/components/interaction/form/FieldGroup/FieldGroup.spec.tsx +129 -7
- package/src/components/interaction/form/FieldGroup/FieldGroup.tsx +72 -12
- package/src/components/interaction/form/FileInput/FileInput.mdx +9 -1
- package/src/components/interaction/form/FileInput/FileInput.module.css +8 -8
- package/src/components/interaction/form/FileInput/FileInput.spec.tsx +89 -1
- package/src/components/interaction/form/FileInput/FileInput.tsx +6 -2
- package/src/components/interaction/form/FormInput/FormInput.mdx +9 -5
- package/src/components/interaction/form/FormInput/FormInput.module.css +17 -8
- package/src/components/interaction/form/FormInput/FormInput.spec.tsx +20 -0
- package/src/components/interaction/form/FormInput/FormInput.tsx +7 -2
- package/src/components/interaction/form/NumberInput/NumberInput.mdx +5 -1
- package/src/components/interaction/form/NumberInput/NumberInput.module.css +6 -6
- package/src/components/interaction/form/NumberInput/NumberInput.spec.tsx +51 -0
- package/src/components/interaction/form/NumberInput/NumberInput.tsx +36 -8
- package/src/components/interaction/form/Radio/Radio.mdx +8 -1
- package/src/components/interaction/form/Radio/Radio.module.css +20 -7
- package/src/components/interaction/form/Radio/Radio.spec.tsx +15 -0
- package/src/components/interaction/form/Radio/Radio.tsx +10 -4
- package/src/components/interaction/form/RadioGroup/RadioGroup.mdx +16 -1
- package/src/components/interaction/form/RadioGroup/RadioGroup.module.css +24 -8
- package/src/components/interaction/form/RadioGroup/RadioGroup.spec.tsx +32 -2
- package/src/components/interaction/form/RadioGroup/RadioGroup.tsx +14 -2
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +9 -3
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +25 -12
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.spec.tsx +86 -5
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +44 -4
- package/src/components/interaction/form/Select/Select.mdx +10 -4
- package/src/components/interaction/form/Select/Select.module.css +4 -4
- package/src/components/interaction/form/Select/Select.spec.tsx +34 -0
- package/src/components/interaction/form/Select/Select.tsx +21 -9
- package/src/components/interaction/form/Slider/Slider.mdx +4 -1
- package/src/components/interaction/form/Slider/Slider.module.css +32 -8
- package/src/components/interaction/form/Slider/Slider.spec.tsx +29 -0
- package/src/components/interaction/form/Slider/Slider.tsx +9 -7
- package/src/components/interaction/form/Switch/Switch.mdx +2 -2
- package/src/components/interaction/form/Switch/Switch.module.css +12 -13
- package/src/components/interaction/form/Switch/Switch.spec.tsx +20 -0
- package/src/components/interaction/form/Switch/Switch.tsx +2 -1
- package/src/components/interaction/form/Textarea/Textarea.mdx +5 -0
- package/src/components/interaction/form/Textarea/Textarea.module.css +5 -5
- package/src/components/interaction/form/Textarea/Textarea.spec.tsx +13 -0
- package/src/components/interaction/form/Textarea/Textarea.tsx +3 -1
- package/src/components/interaction/form/atoms/Message.module.css +1 -1
- package/src/components/interaction/form/atoms/Message.spec.tsx +29 -0
- package/src/components/interaction/form/atoms/Message.tsx +1 -1
- package/src/components/layout/ButtonGroup/ButtonGroup.mdx +11 -0
- package/src/components/layout/ButtonGroup/ButtonGroup.module.css +1 -5
- package/src/components/layout/ButtonGroup/ButtonGroup.stories.tsx +14 -0
- package/src/components/layout/Card/Card.mdx +6 -1
- package/src/components/layout/Card/Card.module.css +26 -5
- package/src/components/layout/Card/Card.spec.tsx +7 -0
- package/src/components/layout/Card/Card.tsx +4 -3
- package/src/components/layout/Grid/Grid.spec.tsx +44 -0
- package/src/components/layout/Grid/Grid.tsx +5 -5
- package/src/components/layout/Grid/GridItem.tsx +6 -6
- package/src/components/layout/Grid/masonry.ts +31 -5
- package/src/components/layout/Grid/useIsomorphicLayoutEffect.ts +11 -0
- package/src/components/layout/IconWrapper/IconWrapper.mdx +8 -2
- package/src/components/layout/IconWrapper/IconWrapper.module.css +9 -6
- package/src/components/layout/SectionHeader/SectionHeader.mdx +4 -1
- package/src/components/layout/SectionHeader/SectionHeader.module.css +10 -9
- package/src/components/ui/Accordion/Accordion.mdx +4 -1
- package/src/components/ui/Accordion/Accordion.module.css +2 -1
- package/src/components/ui/Alert/Alert.mdx +21 -4
- package/src/components/ui/Alert/Alert.module.css +9 -4
- package/src/components/ui/Alert/Alert.spec.tsx +20 -0
- package/src/components/ui/Avatar/Avatar.mdx +8 -3
- package/src/components/ui/Avatar/Avatar.module.css +13 -8
- package/src/components/ui/Badge/Badge.mdx +3 -1
- package/src/components/ui/Breadcrumb/Breadcrumb.mdx +3 -0
- package/src/components/ui/Breadcrumb/Breadcrumb.module.css +4 -0
- package/src/components/ui/Breadcrumb/Breadcrumb.spec.tsx +12 -0
- package/src/components/ui/Breadcrumb/Breadcrumb.tsx +11 -3
- package/src/components/ui/Calendar/Calendar.mdx +6 -0
- package/src/components/ui/Calendar/Calendar.module.css +68 -19
- package/src/components/ui/Calendar/Calendar.spec.tsx +139 -24
- package/src/components/ui/Calendar/Calendar.stories.tsx +14 -0
- package/src/components/ui/Calendar/Calendar.tsx +143 -154
- package/src/components/ui/Calendar/CalendarRange.mdx +39 -0
- package/src/components/ui/Calendar/CalendarRange.spec.tsx +119 -0
- package/src/components/ui/Calendar/CalendarRange.stories.tsx +51 -0
- package/src/components/ui/Calendar/CalendarRange.tsx +213 -0
- package/src/components/ui/Calendar/MonthGrid.tsx +141 -0
- package/src/components/ui/Calendar/calendar-core.spec.ts +176 -0
- package/src/components/ui/Calendar/calendar-core.ts +164 -0
- package/src/components/ui/Calendar/index.ts +1 -0
- package/src/components/ui/Carousel/Carousel.mdx +8 -3
- package/src/components/ui/Carousel/Carousel.module.css +7 -5
- package/src/components/ui/Carousel/Carousel.spec.tsx +67 -0
- package/src/components/ui/Carousel/Carousel.tsx +19 -7
- package/src/components/ui/Collapsible/Collapsible.mdx +17 -6
- package/src/components/ui/Collapsible/Collapsible.module.css +7 -2
- package/src/components/ui/Collapsible/Collapsible.spec.tsx +40 -0
- package/src/components/ui/Collapsible/Collapsible.tsx +19 -2
- package/src/components/ui/DescriptionList/DescriptionList.mdx +2 -0
- package/src/components/ui/Link/Link.mdx +4 -2
- package/src/components/ui/Loading/Loading.mdx +6 -3
- package/src/components/ui/Loading/Loading.module.css +7 -7
- package/src/components/ui/Loading/Loading.spec.tsx +12 -0
- package/src/components/ui/Loading/Loading.tsx +8 -3
- package/src/components/ui/NotificationBanner/NotificationBanner.mdx +4 -0
- package/src/components/ui/NotificationBanner/NotificationBanner.module.css +5 -0
- package/src/components/ui/NotificationBanner/NotificationBanner.spec.tsx +20 -0
- package/src/components/ui/Pagination/Pagination.mdx +29 -7
- package/src/components/ui/Pagination/Pagination.module.css +15 -14
- package/src/components/ui/Progress/Progress.mdx +6 -2
- package/src/components/ui/Progress/Progress.module.css +1 -1
- package/src/components/ui/Progress/Progress.spec.tsx +17 -0
- package/src/components/ui/Progress/Progress.tsx +2 -2
- package/src/components/ui/ProgressCircle/ProgressCircle.mdx +8 -4
- package/src/components/ui/ProgressCircle/ProgressCircle.module.css +2 -2
- package/src/components/ui/ProgressCircle/ProgressCircle.spec.tsx +11 -1
- package/src/components/ui/ProgressCircle/ProgressCircle.tsx +1 -1
- package/src/components/ui/Separator/Separator.mdx +7 -0
- package/src/components/ui/Separator/Separator.module.css +1 -0
- package/src/components/ui/Skeleton/Skeleton.mdx +17 -0
- package/src/components/ui/Skeleton/Skeleton.module.css +12 -5
- package/src/components/ui/SkipLink/SkipLink.mdx +19 -0
- package/src/components/ui/SkipLink/SkipLink.module.css +8 -7
- package/src/components/ui/SkipLink/SkipLink.spec.tsx +28 -0
- package/src/components/ui/Table/Table.mdx +14 -0
- package/src/components/ui/Table/Table.module.css +13 -8
- package/src/components/ui/Table/Table.spec.tsx +56 -0
- package/src/components/ui/Table/Table.tsx +44 -6
- package/src/components/ui/Tabs/Tabs.mdx +16 -0
- package/src/components/ui/Tabs/Tabs.module.css +3 -3
- package/src/components/ui/Tabs/Tabs.spec.tsx +20 -0
- package/src/components/ui/Tabs/Tabs.tsx +5 -1
- package/src/components/ui/Tooltip/Tooltip.mdx +9 -0
- package/src/components/ui/Tooltip/Tooltip.module.css +32 -12
- package/src/components/ui/Tooltip/Tooltip.spec.tsx +56 -0
- package/src/components/ui/Tooltip/Tooltip.tsx +26 -7
- package/src/components/ui/Typography/Typography.mdx +7 -0
- package/src/components/ui/Typography/Typography.module.css +5 -5
- package/src/index.ts +7 -3
- package/src/stories/DesignSystem/Borders.mdx +14 -9
- package/src/stories/DesignSystem/Colors.mdx +43 -41
- package/src/stories/DesignSystem/Overview.mdx +4 -3
- package/src/stories/Introduction.mdx +5 -5
- package/src/web-components/globals.ts +7 -0
- package/src/web-components/index.ts +2 -0
- package/src/web-components/interaction/BdsAccordion.mdx +10 -1
- package/src/web-components/interaction/BdsButton.mdx +15 -4
- package/src/web-components/interaction/BdsButton.stories.tsx +1 -1
- package/src/web-components/interaction/BdsCollapsible.mdx +3 -3
- package/src/web-components/interaction/BdsDialog.mdx +12 -7
- package/src/web-components/interaction/BdsDialog.stories.tsx +2 -2
- package/src/web-components/interaction/BdsDrawer.mdx +9 -6
- package/src/web-components/interaction/BdsDropdownMenu.mdx +20 -1
- package/src/web-components/interaction/BdsPopover.mdx +7 -3
- package/src/web-components/interaction/BdsSkipLink.mdx +14 -1
- package/src/web-components/interaction/BdsTabs.mdx +18 -1
- package/src/web-components/interaction/BdsToastProvider.mdx +21 -3
- package/src/web-components/interaction/BdsTooltip.mdx +4 -4
- package/src/web-components/interaction/bds-accordion-item.ts +10 -0
- package/src/web-components/interaction/bds-accordion.spec.ts +41 -0
- package/src/web-components/interaction/bds-accordion.ts +28 -2
- package/src/web-components/interaction/bds-button.spec.ts +81 -0
- package/src/web-components/interaction/bds-button.ts +60 -13
- package/src/web-components/interaction/bds-collapsible.spec.ts +93 -2
- package/src/web-components/interaction/bds-collapsible.ts +49 -7
- package/src/web-components/interaction/bds-dialog.spec.ts +49 -0
- package/src/web-components/interaction/bds-dialog.ts +68 -11
- package/src/web-components/interaction/bds-drawer.spec.ts +93 -4
- package/src/web-components/interaction/bds-drawer.ts +54 -21
- package/src/web-components/interaction/bds-dropdown-menu-item.ts +12 -1
- package/src/web-components/interaction/bds-dropdown-menu.spec.ts +63 -0
- package/src/web-components/interaction/bds-dropdown-menu.ts +45 -7
- package/src/web-components/interaction/bds-popover.spec.ts +80 -6
- package/src/web-components/interaction/bds-popover.ts +83 -32
- package/src/web-components/interaction/bds-skip-link.spec.ts +18 -0
- package/src/web-components/interaction/bds-skip-link.ts +29 -8
- package/src/web-components/interaction/bds-tab-panel.ts +10 -0
- package/src/web-components/interaction/bds-tab.spec.ts +25 -0
- package/src/web-components/interaction/bds-tab.ts +20 -5
- package/src/web-components/interaction/bds-tabs.spec.ts +92 -5
- package/src/web-components/interaction/bds-tabs.ts +42 -1
- package/src/web-components/interaction/bds-toast-provider.spec.ts +43 -0
- package/src/web-components/interaction/bds-toast-provider.ts +50 -21
- package/src/web-components/interaction/bds-tooltip.spec.ts +71 -0
- package/src/web-components/interaction/bds-tooltip.ts +100 -5
- package/src/web-components/interaction/form/BdsCheckbox.mdx +20 -1
- package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +8 -0
- package/src/web-components/interaction/form/BdsCheckboxGroup.mdx +4 -3
- package/src/web-components/interaction/form/BdsCombobox.mdx +39 -2
- package/src/web-components/interaction/form/BdsCombobox.stories.tsx +31 -0
- package/src/web-components/interaction/form/BdsFieldGroup.mdx +8 -3
- package/src/web-components/interaction/form/BdsFieldGroup.stories.tsx +1 -1
- package/src/web-components/interaction/form/BdsFileInput.mdx +26 -5
- package/src/web-components/interaction/form/BdsFormInput.mdx +16 -1
- package/src/web-components/interaction/form/BdsNumberInput.mdx +34 -2
- package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +27 -3
- package/src/web-components/interaction/form/BdsRadio.mdx +39 -12
- package/src/web-components/interaction/form/BdsRadio.stories.tsx +26 -0
- package/src/web-components/interaction/form/BdsRadioGroup.mdx +9 -4
- package/src/web-components/interaction/form/BdsSegmentedControl.mdx +37 -11
- package/src/web-components/interaction/form/BdsSelect.mdx +22 -4
- package/src/web-components/interaction/form/BdsSelect.stories.tsx +33 -0
- package/src/web-components/interaction/form/BdsSlider.mdx +36 -19
- package/src/web-components/interaction/form/BdsSlider.stories.tsx +24 -0
- package/src/web-components/interaction/form/BdsSwitch.mdx +38 -11
- package/src/web-components/interaction/form/BdsSwitch.stories.tsx +16 -0
- package/src/web-components/interaction/form/BdsTextarea.mdx +42 -16
- package/src/web-components/interaction/form/BdsTextarea.stories.tsx +21 -0
- package/src/web-components/interaction/form/bds-checkbox-group.spec.ts +99 -0
- package/src/web-components/interaction/form/bds-checkbox-group.ts +95 -9
- package/src/web-components/interaction/form/bds-checkbox.spec.ts +55 -0
- package/src/web-components/interaction/form/bds-checkbox.ts +30 -5
- package/src/web-components/interaction/form/bds-combobox.spec.ts +79 -0
- package/src/web-components/interaction/form/bds-combobox.ts +102 -17
- package/src/web-components/interaction/form/bds-field-group.spec.ts +158 -0
- package/src/web-components/interaction/form/bds-field-group.ts +167 -23
- package/src/web-components/interaction/form/bds-file-input.spec.ts +73 -5
- package/src/web-components/interaction/form/bds-file-input.ts +71 -34
- package/src/web-components/interaction/form/bds-form-input.spec.ts +22 -0
- package/src/web-components/interaction/form/bds-form-input.ts +27 -16
- package/src/web-components/interaction/form/bds-number-input.spec.ts +49 -0
- package/src/web-components/interaction/form/bds-number-input.ts +118 -29
- package/src/web-components/interaction/form/bds-radio-group.spec.ts +57 -0
- package/src/web-components/interaction/form/bds-radio-group.ts +60 -12
- package/src/web-components/interaction/form/bds-radio.spec.ts +123 -0
- package/src/web-components/interaction/form/bds-radio.ts +136 -23
- package/src/web-components/interaction/form/bds-segmented-control.spec.ts +55 -0
- package/src/web-components/interaction/form/bds-segmented-control.ts +81 -59
- package/src/web-components/interaction/form/bds-select.spec.ts +57 -0
- package/src/web-components/interaction/form/bds-select.ts +96 -8
- package/src/web-components/interaction/form/bds-slider.spec.ts +83 -0
- package/src/web-components/interaction/form/bds-slider.ts +181 -33
- package/src/web-components/interaction/form/bds-switch.spec.ts +68 -0
- package/src/web-components/interaction/form/bds-switch.ts +142 -41
- package/src/web-components/interaction/form/bds-textarea.spec.ts +71 -0
- package/src/web-components/interaction/form/bds-textarea.ts +109 -8
- package/src/web-components/layout/BdsGrid.mdx +6 -2
- package/src/web-components/layout/BdsGrid.stories.tsx +4 -0
- package/src/web-components/layout/bds-grid-item.spec.ts +21 -0
- package/src/web-components/layout/bds-grid-item.ts +17 -3
- package/src/web-components/layout/bds-grid.spec.ts +98 -0
- package/src/web-components/layout/bds-grid.ts +139 -19
- package/src/web-components/ui/BdsAlert.mdx +6 -5
- package/src/web-components/ui/BdsAlert.stories.tsx +6 -6
- package/src/web-components/ui/BdsAvatar.mdx +4 -2
- package/src/web-components/ui/BdsBreadcrumb.mdx +3 -2
- package/src/web-components/ui/BdsButtonContainer.mdx +64 -0
- package/src/web-components/ui/BdsButtonContainer.stories.tsx +84 -0
- package/src/web-components/ui/BdsCalendar.mdx +29 -4
- package/src/web-components/ui/BdsCalendar.stories.tsx +16 -18
- package/src/web-components/ui/BdsCalendarRange.mdx +71 -0
- package/src/web-components/ui/BdsCalendarRange.stories.tsx +31 -0
- package/src/web-components/ui/BdsCard.mdx +7 -3
- package/src/web-components/ui/BdsCard.stories.tsx +17 -1
- package/src/web-components/ui/BdsCarousel.mdx +40 -12
- package/src/web-components/ui/BdsDescriptionList.mdx +6 -1
- package/src/web-components/ui/BdsIconWrapper.mdx +3 -2
- package/src/web-components/ui/BdsLink.mdx +14 -2
- package/src/web-components/ui/BdsNotificationBanner.mdx +18 -0
- package/src/web-components/ui/BdsPagination.mdx +40 -1
- package/src/web-components/ui/BdsProgress.mdx +8 -2
- package/src/web-components/ui/BdsProgressCircle.mdx +5 -2
- package/src/web-components/ui/BdsRating.mdx +7 -0
- package/src/web-components/ui/BdsSectionHeader.mdx +22 -3
- package/src/web-components/ui/BdsSectionHeader.stories.tsx +15 -13
- package/src/web-components/ui/BdsTable.mdx +23 -2
- package/src/web-components/ui/BdsTable.stories.tsx +8 -2
- package/src/web-components/ui/BdsTypography.mdx +17 -1
- package/src/web-components/ui/bds-alert.spec.ts +17 -2
- package/src/web-components/ui/bds-alert.ts +31 -5
- package/src/web-components/ui/bds-avatar.spec.ts +29 -0
- package/src/web-components/ui/bds-avatar.ts +30 -12
- package/src/web-components/ui/bds-badge.spec.ts +5 -0
- package/src/web-components/ui/bds-badge.ts +11 -1
- package/src/web-components/ui/bds-breadcrumb.spec.ts +30 -0
- package/src/web-components/ui/bds-breadcrumb.ts +26 -4
- package/src/web-components/ui/bds-button-container.spec.ts +39 -0
- package/src/web-components/ui/bds-button-container.ts +123 -0
- package/src/web-components/ui/bds-button-group.spec.ts +14 -20
- package/src/web-components/ui/bds-button-group.ts +13 -64
- package/src/web-components/ui/bds-calendar-range.spec.ts +123 -0
- package/src/web-components/ui/bds-calendar-range.ts +307 -0
- package/src/web-components/ui/bds-calendar.spec.ts +176 -0
- package/src/web-components/ui/bds-calendar.ts +186 -344
- package/src/web-components/ui/bds-card.spec.ts +32 -0
- package/src/web-components/ui/bds-card.ts +34 -9
- package/src/web-components/ui/bds-carousel.spec.ts +147 -0
- package/src/web-components/ui/bds-carousel.ts +113 -36
- package/src/web-components/ui/bds-description-list.spec.ts +15 -0
- package/src/web-components/ui/bds-description-list.ts +37 -3
- package/src/web-components/ui/bds-icon-wrapper.spec.ts +12 -0
- package/src/web-components/ui/bds-icon-wrapper.ts +16 -15
- package/src/web-components/ui/bds-link.spec.ts +17 -0
- package/src/web-components/ui/bds-link.ts +26 -11
- package/src/web-components/ui/bds-loading.ts +11 -1
- package/src/web-components/ui/bds-notification-banner.spec.ts +13 -0
- package/src/web-components/ui/bds-notification-banner.ts +18 -1
- package/src/web-components/ui/bds-pagination.spec.ts +44 -0
- package/src/web-components/ui/bds-pagination.ts +39 -19
- package/src/web-components/ui/bds-progress-circle.spec.ts +21 -0
- package/src/web-components/ui/bds-progress-circle.ts +17 -5
- package/src/web-components/ui/bds-progress.spec.ts +21 -0
- package/src/web-components/ui/bds-progress.ts +19 -6
- package/src/web-components/ui/bds-rating.spec.ts +6 -0
- package/src/web-components/ui/bds-rating.ts +12 -2
- package/src/web-components/ui/bds-section-header.spec.ts +39 -8
- package/src/web-components/ui/bds-section-header.ts +47 -13
- package/src/web-components/ui/bds-separator.ts +10 -0
- package/src/web-components/ui/bds-skeleton.ts +10 -0
- package/src/web-components/ui/bds-table.spec.ts +63 -0
- package/src/web-components/ui/bds-table.ts +88 -28
- package/src/web-components/ui/bds-typography.spec.ts +47 -0
- package/src/web-components/ui/bds-typography.ts +28 -10
- package/src/web-components/ui/calendar-styles.ts +94 -0
- package/dist/web-components/chunk-5TFWOPLH.js +0 -49
- package/dist/web-components/chunk-7FMR53BW.js +0 -127
- package/dist/web-components/chunk-AGKJTMJI.js +0 -56
- package/dist/web-components/chunk-BQLZ7I4G.js +0 -56
- package/dist/web-components/chunk-IYGF6CD5.js +0 -118
- package/dist/web-components/chunk-QBB6ZX4R.js +0 -107
- package/dist/web-components/chunk-Y3POAKGS.js +0 -133
- package/dist/web-components/chunk-Y4MAXTMA.js +0 -80
- package/dist/web-components/chunk-Y7V7LM6R.js +0 -98
- package/src/web-components/ui/BdsButtonGroup.mdx +0 -69
- package/src/web-components/ui/BdsButtonGroup.stories.tsx +0 -66
|
@@ -37,12 +37,29 @@ describe('bds-collapsible', () => {
|
|
|
37
37
|
const el = await fixture('<bds-collapsible><span slot="summary">Title</span><p>Content</p></bds-collapsible>') as BdsCollapsible;
|
|
38
38
|
const handler = vi.fn();
|
|
39
39
|
el.addEventListener('bds-toggle', handler);
|
|
40
|
-
// jsdom does not
|
|
41
|
-
//
|
|
40
|
+
// jsdom does not simulate a real click-driven state change, so emulate it:
|
|
41
|
+
// flip the native <details> element's own `open` property first (what the
|
|
42
|
+
// browser does before dispatching), then fire the "toggle" event it would emit.
|
|
42
43
|
const details = el.shadowRoot!.querySelector('details')!;
|
|
44
|
+
details.open = true;
|
|
43
45
|
details.dispatchEvent(new Event('toggle', { bubbles: false }));
|
|
44
46
|
await el.updateComplete;
|
|
45
47
|
expect(handler).toHaveBeenCalledOnce();
|
|
48
|
+
expect(handler.mock.calls[0][0].detail).toEqual({ open: true });
|
|
49
|
+
expect(el.open).toBe(true);
|
|
50
|
+
cleanup(el);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('does not dispatch a redundant bds-toggle when the toggle event fires without a real state change', async () => {
|
|
54
|
+
const el = await fixture('<bds-collapsible><span slot="summary">Title</span><p>Content</p></bds-collapsible>') as BdsCollapsible;
|
|
55
|
+
const handler = vi.fn();
|
|
56
|
+
el.addEventListener('bds-toggle', handler);
|
|
57
|
+
// Native <details> "toggle" event coalesces and only fires on real state changes;
|
|
58
|
+
// a spurious dispatch with no actual open-state change must be a no-op.
|
|
59
|
+
const details = el.shadowRoot!.querySelector('details')!;
|
|
60
|
+
details.dispatchEvent(new Event('toggle', { bubbles: false }));
|
|
61
|
+
await el.updateComplete;
|
|
62
|
+
expect(handler).not.toHaveBeenCalled();
|
|
46
63
|
cleanup(el);
|
|
47
64
|
});
|
|
48
65
|
|
|
@@ -53,4 +70,78 @@ describe('bds-collapsible', () => {
|
|
|
53
70
|
expect(el.getAttribute('open')).not.toBeNull();
|
|
54
71
|
cleanup(el);
|
|
55
72
|
});
|
|
73
|
+
|
|
74
|
+
describe('name grouping (exclusive open)', () => {
|
|
75
|
+
it('closes other open members of the same group when one opens', async () => {
|
|
76
|
+
const a = await fixture(
|
|
77
|
+
'<bds-collapsible name="faq" open><span slot="summary">A</span><p>Content A</p></bds-collapsible>',
|
|
78
|
+
) as BdsCollapsible;
|
|
79
|
+
const b = await fixture(
|
|
80
|
+
'<bds-collapsible name="faq"><span slot="summary">B</span><p>Content B</p></bds-collapsible>',
|
|
81
|
+
) as BdsCollapsible;
|
|
82
|
+
expect(a.open).toBe(true);
|
|
83
|
+
|
|
84
|
+
b.open = true;
|
|
85
|
+
await b.updateComplete;
|
|
86
|
+
await a.updateComplete;
|
|
87
|
+
|
|
88
|
+
expect(b.open).toBe(true);
|
|
89
|
+
expect(a.open).toBe(false);
|
|
90
|
+
expect(a.hasAttribute('open')).toBe(false);
|
|
91
|
+
cleanup(a);
|
|
92
|
+
cleanup(b);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('fires bds-toggle on the sibling that gets force-closed', async () => {
|
|
96
|
+
const a = await fixture(
|
|
97
|
+
'<bds-collapsible name="faq" open><span slot="summary">A</span><p>Content A</p></bds-collapsible>',
|
|
98
|
+
) as BdsCollapsible;
|
|
99
|
+
const b = await fixture(
|
|
100
|
+
'<bds-collapsible name="faq"><span slot="summary">B</span><p>Content B</p></bds-collapsible>',
|
|
101
|
+
) as BdsCollapsible;
|
|
102
|
+
const aHandler = vi.fn();
|
|
103
|
+
a.addEventListener('bds-toggle', aHandler);
|
|
104
|
+
|
|
105
|
+
b.open = true;
|
|
106
|
+
await b.updateComplete;
|
|
107
|
+
await a.updateComplete;
|
|
108
|
+
|
|
109
|
+
expect(aHandler).toHaveBeenCalledOnce();
|
|
110
|
+
expect(aHandler.mock.calls[0][0].detail).toEqual({ open: false });
|
|
111
|
+
cleanup(a);
|
|
112
|
+
cleanup(b);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('does not affect open collapsibles in a different group', async () => {
|
|
116
|
+
const a = await fixture(
|
|
117
|
+
'<bds-collapsible name="faq" open><span slot="summary">A</span><p>Content A</p></bds-collapsible>',
|
|
118
|
+
) as BdsCollapsible;
|
|
119
|
+
const b = await fixture(
|
|
120
|
+
'<bds-collapsible name="other"><span slot="summary">B</span><p>Content B</p></bds-collapsible>',
|
|
121
|
+
) as BdsCollapsible;
|
|
122
|
+
|
|
123
|
+
b.open = true;
|
|
124
|
+
await b.updateComplete;
|
|
125
|
+
await a.updateComplete;
|
|
126
|
+
|
|
127
|
+
expect(a.open).toBe(true);
|
|
128
|
+
expect(b.open).toBe(true);
|
|
129
|
+
cleanup(a);
|
|
130
|
+
cleanup(b);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('does not group collapsibles with no name attribute', async () => {
|
|
134
|
+
const a = await fixture('<bds-collapsible open><span slot="summary">A</span><p>Content A</p></bds-collapsible>') as BdsCollapsible;
|
|
135
|
+
const b = await fixture('<bds-collapsible><span slot="summary">B</span><p>Content B</p></bds-collapsible>') as BdsCollapsible;
|
|
136
|
+
|
|
137
|
+
b.open = true;
|
|
138
|
+
await b.updateComplete;
|
|
139
|
+
await a.updateComplete;
|
|
140
|
+
|
|
141
|
+
expect(a.open).toBe(true);
|
|
142
|
+
expect(b.open).toBe(true);
|
|
143
|
+
cleanup(a);
|
|
144
|
+
cleanup(b);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
56
147
|
});
|
|
@@ -7,8 +7,11 @@ import { LitElement, css, html } from 'lit';
|
|
|
7
7
|
*
|
|
8
8
|
* Attributes:
|
|
9
9
|
* open — boolean; controlled open state
|
|
10
|
-
* name — groups multiple collapsibles so only one is open at a time
|
|
11
|
-
*
|
|
10
|
+
* name — groups multiple collapsibles so only one is open at a time.
|
|
11
|
+
* Each instance renders its own <details> in its own shadow root, so
|
|
12
|
+
* native <details name> grouping (tree-scoped) can't see across
|
|
13
|
+
* instances; the component emulates it by closing same-name siblings
|
|
14
|
+
* found via document.querySelectorAll() whenever one opens.
|
|
12
15
|
*
|
|
13
16
|
* Slots:
|
|
14
17
|
* summary — the always-visible trigger text
|
|
@@ -26,6 +29,16 @@ import { LitElement, css, html } from 'lit';
|
|
|
26
29
|
*/
|
|
27
30
|
export class BdsCollapsible extends LitElement {
|
|
28
31
|
static styles = css`
|
|
32
|
+
/* Shadow DOM does not inherit the global box-sizing reset, so set it
|
|
33
|
+
here; otherwise elements with an explicit size + padding size as
|
|
34
|
+
content-box and layouts drift from the React (light-DOM) versions. */
|
|
35
|
+
:host,
|
|
36
|
+
*,
|
|
37
|
+
*::before,
|
|
38
|
+
*::after {
|
|
39
|
+
box-sizing: border-box;
|
|
40
|
+
}
|
|
41
|
+
|
|
29
42
|
:host {
|
|
30
43
|
display: block;
|
|
31
44
|
}
|
|
@@ -91,7 +104,9 @@ export class BdsCollapsible extends LitElement {
|
|
|
91
104
|
|
|
92
105
|
.content {
|
|
93
106
|
padding: var(--bds-space_m);
|
|
94
|
-
|
|
107
|
+
/* React counterpart leaves the content panel transparent; keep the override
|
|
108
|
+
hook for consumers but default it to match, not to --bds-color_bg. */
|
|
109
|
+
background-color: var(--collapsible_content-bg, transparent);
|
|
95
110
|
color: var(--collapsible_on-color, var(--bds-color_on-bg));
|
|
96
111
|
font-size: var(--bds-font_size--body);
|
|
97
112
|
line-height: var(--bds-font_line-height--body);
|
|
@@ -131,20 +146,47 @@ export class BdsCollapsible extends LitElement {
|
|
|
131
146
|
}
|
|
132
147
|
}
|
|
133
148
|
}
|
|
149
|
+
|
|
150
|
+
// Emulate native <details name="…"> exclusive-open grouping ourselves: each
|
|
151
|
+
// bds-collapsible renders its own <details> inside its own shadow root, so the
|
|
152
|
+
// browser's built-in name-based grouping is tree-scoped per shadow root and never
|
|
153
|
+
// sees siblings. Whenever this instance opens, close any other open member of the
|
|
154
|
+
// same group.
|
|
155
|
+
if (changed.has('open') && this.open && this.name) {
|
|
156
|
+
this._closeOtherGroupMembers();
|
|
157
|
+
}
|
|
134
158
|
}
|
|
135
159
|
|
|
136
|
-
private
|
|
137
|
-
const
|
|
138
|
-
|
|
160
|
+
private _closeOtherGroupMembers() {
|
|
161
|
+
const groupName = this.name;
|
|
162
|
+
document.querySelectorAll('bds-collapsible').forEach((el) => {
|
|
163
|
+
if (el !== this && el.name === groupName && el.open) {
|
|
164
|
+
el._setOpen(false);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// State-guarded setter: returns early once already in the target state so a
|
|
170
|
+
// native <details> "toggle" event re-fired by the browser after a script-driven
|
|
171
|
+
// attribute change (see the toggle event spec's coalescing note) never dispatches
|
|
172
|
+
// a redundant bds-toggle.
|
|
173
|
+
private _setOpen(newOpen: boolean) {
|
|
174
|
+
if (this.open === newOpen) return;
|
|
175
|
+
this.open = newOpen;
|
|
139
176
|
this.dispatchEvent(
|
|
140
177
|
new CustomEvent('bds-toggle', {
|
|
141
178
|
bubbles: true,
|
|
142
179
|
composed: true,
|
|
143
|
-
detail: { open:
|
|
180
|
+
detail: { open: newOpen },
|
|
144
181
|
}),
|
|
145
182
|
);
|
|
146
183
|
}
|
|
147
184
|
|
|
185
|
+
private _onToggle(e: Event) {
|
|
186
|
+
const details = e.currentTarget as HTMLDetailsElement;
|
|
187
|
+
this._setOpen(details.open);
|
|
188
|
+
}
|
|
189
|
+
|
|
148
190
|
render() {
|
|
149
191
|
return html`
|
|
150
192
|
<details
|
|
@@ -116,4 +116,53 @@ describe('bds-dialog', () => {
|
|
|
116
116
|
expect(el.querySelector('p')!.textContent).toBe('Hello world');
|
|
117
117
|
cleanup(el);
|
|
118
118
|
});
|
|
119
|
+
|
|
120
|
+
it('responds to the --show-modal custom command', async () => {
|
|
121
|
+
const el = await fixture('<bds-dialog><p>Content</p></bds-dialog>') as BdsDialog;
|
|
122
|
+
expect(el.open).toBeFalsy();
|
|
123
|
+
el.dispatchEvent(makeCommandEvent('--show-modal'));
|
|
124
|
+
await el.updateComplete;
|
|
125
|
+
expect(el.open).toBe(true);
|
|
126
|
+
expect(HTMLDialogElement.prototype.showModal).toHaveBeenCalled();
|
|
127
|
+
cleanup(el);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('responds to the --close custom command', async () => {
|
|
131
|
+
const el = await fixture('<bds-dialog open><p>Content</p></bds-dialog>') as BdsDialog;
|
|
132
|
+
el.dispatchEvent(makeCommandEvent('--close'));
|
|
133
|
+
await el.updateComplete;
|
|
134
|
+
expect(el.open).toBe(false);
|
|
135
|
+
expect(HTMLDialogElement.prototype.close).toHaveBeenCalled();
|
|
136
|
+
cleanup(el);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('releases the body scroll lock when disconnected while open', async () => {
|
|
140
|
+
const el = await fixture('<bds-dialog open><p>Content</p></bds-dialog>') as BdsDialog;
|
|
141
|
+
expect(document.body.style.overflow).toBe('hidden');
|
|
142
|
+
el.remove();
|
|
143
|
+
expect(document.body.style.overflow).toBe('');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('forwards host aria-label to the shadow dialog', async () => {
|
|
147
|
+
const el = await fixture('<bds-dialog aria-label="Confirm deletion"><p>Content</p></bds-dialog>');
|
|
148
|
+
const dialog = el.shadowRoot!.querySelector('dialog')!;
|
|
149
|
+
expect(dialog.getAttribute('aria-label')).toBe('Confirm deletion');
|
|
150
|
+
cleanup(el);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('omits aria-label on the shadow dialog when unset', async () => {
|
|
154
|
+
const el = await fixture('<bds-dialog><p>Content</p></bds-dialog>');
|
|
155
|
+
const dialog = el.shadowRoot!.querySelector('dialog')!;
|
|
156
|
+
expect(dialog.hasAttribute('aria-label')).toBe(false);
|
|
157
|
+
cleanup(el);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('lays out the dialog as a flex column so dialog-content can scroll internally', () => {
|
|
161
|
+
expect(BdsDialog.styles.cssText).toMatch(/\.dialog\s*{[^}]*display:\s*flex/);
|
|
162
|
+
expect(BdsDialog.styles.cssText).toMatch(/\.dialog\s*{[^}]*flex-direction:\s*column/);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('close button has a :focus-visible outline rule', () => {
|
|
166
|
+
expect(BdsDialog.styles.cssText).toMatch(/\.close-button:focus-visible\s*{[^}]*outline:/);
|
|
167
|
+
});
|
|
119
168
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LitElement, css, html } from 'lit';
|
|
1
|
+
import { LitElement, css, html, nothing } from 'lit';
|
|
2
2
|
|
|
3
3
|
const FOCUSABLE = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
|
|
4
4
|
|
|
@@ -7,10 +7,13 @@ const FOCUSABLE = 'button, [href], input, select, textarea, [tabindex]:not([tabi
|
|
|
7
7
|
*
|
|
8
8
|
* Wraps a native `<dialog>` element with `showModal()` / `close()` lifecycle,
|
|
9
9
|
* backdrop-click to dismiss, Escape key handling, Tab focus trapping, and
|
|
10
|
-
* the Invoker Commands API (
|
|
10
|
+
* the Invoker Commands API (custom commands `--show-modal` / `--close`; the
|
|
11
|
+
* unprefixed `show-modal` / `close` values are still accepted for
|
|
12
|
+
* compatibility with polyfilled/legacy environments).
|
|
11
13
|
*
|
|
12
14
|
* Attributes:
|
|
13
15
|
* open — boolean; controlled open state (syncs to native showModal/close)
|
|
16
|
+
* aria-label — accessible name forwarded to the inner shadow <dialog>
|
|
14
17
|
*
|
|
15
18
|
* Slots:
|
|
16
19
|
* (default) — dialog content
|
|
@@ -20,13 +23,23 @@ const FOCUSABLE = 'button, [href], input, select, textarea, [tabindex]:not([tabi
|
|
|
20
23
|
* bds-close — fired (bubbles, composed) when the dialog closes
|
|
21
24
|
*
|
|
22
25
|
* @example
|
|
23
|
-
* <bds-dialog id="my-dialog">
|
|
26
|
+
* <bds-dialog id="my-dialog" aria-label="Confirm deletion">
|
|
24
27
|
* <p>Dialog content</p>
|
|
25
28
|
* </bds-dialog>
|
|
26
|
-
* <button commandfor="my-dialog" command="show-modal">Open</button>
|
|
29
|
+
* <button commandfor="my-dialog" command="--show-modal">Open</button>
|
|
27
30
|
*/
|
|
28
31
|
export class BdsDialog extends LitElement {
|
|
29
32
|
static styles = css`
|
|
33
|
+
/* Shadow DOM does not inherit the global box-sizing reset, so set it
|
|
34
|
+
here; otherwise elements with an explicit size + padding size as
|
|
35
|
+
content-box and layouts drift from the React (light-DOM) versions. */
|
|
36
|
+
:host,
|
|
37
|
+
*,
|
|
38
|
+
*::before,
|
|
39
|
+
*::after {
|
|
40
|
+
box-sizing: border-box;
|
|
41
|
+
}
|
|
42
|
+
|
|
30
43
|
:host {
|
|
31
44
|
display: contents;
|
|
32
45
|
}
|
|
@@ -34,9 +47,11 @@ export class BdsDialog extends LitElement {
|
|
|
34
47
|
.dialog {
|
|
35
48
|
font-size: var(--bds-font_size--body--s);
|
|
36
49
|
border: var(--dialog_border, none);
|
|
37
|
-
--bdc_color:
|
|
50
|
+
--bdc_color: currentcolor;
|
|
38
51
|
--bdc-outline_radius: var(--bds-border_radius--m);
|
|
39
52
|
|
|
53
|
+
display: flex;
|
|
54
|
+
flex-direction: column;
|
|
40
55
|
border-radius: var(--dialog_radius, var(--bdc-outline_radius));
|
|
41
56
|
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--dialog_shadow, var(--bdc-outline_shadow));
|
|
42
57
|
background-color: var(--dialog_color, var(--bds-color_grey--subtle));
|
|
@@ -44,10 +59,19 @@ export class BdsDialog extends LitElement {
|
|
|
44
59
|
padding: var(--bds-space_l);
|
|
45
60
|
max-inline-size: 90svw;
|
|
46
61
|
max-block-size: 90svh;
|
|
62
|
+
|
|
63
|
+
/* visible (not hidden) so the close button, offset outside the box via
|
|
64
|
+
inset-*: -1em, is never clipped; .dialog-content scrolls internally. */
|
|
47
65
|
overflow: visible;
|
|
48
66
|
position: relative;
|
|
49
67
|
}
|
|
50
68
|
|
|
69
|
+
/* A native <dialog> is display:none until opened; the flex layout above
|
|
70
|
+
would otherwise override the UA rule and render the dialog permanently. */
|
|
71
|
+
.dialog:not([open]) {
|
|
72
|
+
display: none;
|
|
73
|
+
}
|
|
74
|
+
|
|
51
75
|
.dialog-content {
|
|
52
76
|
display: grid;
|
|
53
77
|
gap: var(--bds-grid_gap);
|
|
@@ -70,12 +94,26 @@ export class BdsDialog extends LitElement {
|
|
|
70
94
|
background-color: var(--bds-color_bg);
|
|
71
95
|
color: currentcolor;
|
|
72
96
|
border: var(--dialog_close-border, none);
|
|
73
|
-
--bdc_color:
|
|
97
|
+
--bdc_color: currentcolor;
|
|
74
98
|
|
|
75
99
|
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color);
|
|
76
100
|
cursor: pointer;
|
|
77
101
|
}
|
|
78
102
|
|
|
103
|
+
/* Extend the hit area to the 44x44px minimum touch target (WCAG 2.5.5)
|
|
104
|
+
without growing the visual 2em disc. */
|
|
105
|
+
.close-button::after {
|
|
106
|
+
content: '';
|
|
107
|
+
position: absolute;
|
|
108
|
+
inset-block: -0.5rem;
|
|
109
|
+
inset-inline: -0.5rem;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.close-button:focus-visible {
|
|
113
|
+
outline: var(--bds-outline_default);
|
|
114
|
+
outline-offset: var(--bds-outline_offset);
|
|
115
|
+
}
|
|
116
|
+
|
|
79
117
|
.close-button svg {
|
|
80
118
|
inline-size: 1.25em;
|
|
81
119
|
block-size: 1.25em;
|
|
@@ -88,16 +126,19 @@ export class BdsDialog extends LitElement {
|
|
|
88
126
|
`;
|
|
89
127
|
|
|
90
128
|
static properties = {
|
|
91
|
-
open:
|
|
129
|
+
open: { type: Boolean, reflect: true },
|
|
130
|
+
ariaLabel: { type: String, attribute: 'aria-label' },
|
|
92
131
|
};
|
|
93
132
|
|
|
94
133
|
declare open: boolean;
|
|
134
|
+
declare ariaLabel: string | null;
|
|
95
135
|
|
|
96
136
|
private _triggerEl: Element | null = null;
|
|
97
137
|
|
|
98
138
|
constructor() {
|
|
99
139
|
super();
|
|
100
140
|
this.open = false;
|
|
141
|
+
this.ariaLabel = null;
|
|
101
142
|
}
|
|
102
143
|
|
|
103
144
|
connectedCallback() {
|
|
@@ -108,6 +149,13 @@ export class BdsDialog extends LitElement {
|
|
|
108
149
|
disconnectedCallback() {
|
|
109
150
|
super.disconnectedCallback();
|
|
110
151
|
this.removeEventListener('command', this._onCommand);
|
|
152
|
+
// Release the body scroll-lock if the dialog is removed from the DOM
|
|
153
|
+
// while still open — otherwise the lock leaks and the page stays
|
|
154
|
+
// non-scrollable forever.
|
|
155
|
+
if (this.open) {
|
|
156
|
+
document.body.style.overflow = '';
|
|
157
|
+
this._triggerEl = null;
|
|
158
|
+
}
|
|
111
159
|
}
|
|
112
160
|
|
|
113
161
|
updated(changed: Map<string, unknown>) {
|
|
@@ -134,8 +182,12 @@ export class BdsDialog extends LitElement {
|
|
|
134
182
|
|
|
135
183
|
private _onCommand = (e: Event) => {
|
|
136
184
|
const command = (e as CommandEvent).command;
|
|
137
|
-
|
|
138
|
-
|
|
185
|
+
// Custom (`--`-prefixed) commands are what the Invoker Commands API
|
|
186
|
+
// actually dispatches on a non-<dialog> custom-element target — the
|
|
187
|
+
// unprefixed "show-modal"/"close" keywords are still accepted so
|
|
188
|
+
// programmatic dispatches and polyfilled environments keep working.
|
|
189
|
+
if (command === '--show-modal' || command === 'show-modal') this._openDialog();
|
|
190
|
+
else if (command === '--close' || command === 'close') this._closeDialog();
|
|
139
191
|
};
|
|
140
192
|
|
|
141
193
|
private _openDialog() {
|
|
@@ -178,10 +230,14 @@ export class BdsDialog extends LitElement {
|
|
|
178
230
|
if (all.length === 0) return;
|
|
179
231
|
const first = all[0];
|
|
180
232
|
const last = all[all.length - 1];
|
|
233
|
+
// Focus inside the shadow tree (e.g. the close button) resolves via
|
|
234
|
+
// shadowRoot.activeElement — document.activeElement only ever reports
|
|
235
|
+
// the host element for shadow-internal focus.
|
|
236
|
+
const active = this.shadowRoot?.activeElement ?? document.activeElement;
|
|
181
237
|
if (e.shiftKey) {
|
|
182
|
-
if (
|
|
238
|
+
if (active === first) { e.preventDefault(); last.focus(); }
|
|
183
239
|
} else {
|
|
184
|
-
if (
|
|
240
|
+
if (active === last) { e.preventDefault(); first.focus(); }
|
|
185
241
|
}
|
|
186
242
|
}
|
|
187
243
|
|
|
@@ -190,6 +246,7 @@ export class BdsDialog extends LitElement {
|
|
|
190
246
|
<dialog
|
|
191
247
|
class="dialog"
|
|
192
248
|
aria-modal="true"
|
|
249
|
+
aria-label=${this.ariaLabel ?? nothing}
|
|
193
250
|
@click=${this._handleBackdropClick}
|
|
194
251
|
@cancel=${this._handleCancel}
|
|
195
252
|
@keydown=${this._handleKeydown}
|
|
@@ -71,24 +71,33 @@ describe('bds-drawer', () => {
|
|
|
71
71
|
cleanup(el);
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
it('fires bds-open on show-modal command', async () => {
|
|
74
|
+
it('fires bds-open on --show-modal command', async () => {
|
|
75
75
|
const el = await fixture('<bds-drawer><p>Content</p></bds-drawer>');
|
|
76
76
|
const handler = vi.fn();
|
|
77
77
|
el.addEventListener('bds-open', handler);
|
|
78
|
-
el.dispatchEvent(makeCommandEvent('show-modal'));
|
|
78
|
+
el.dispatchEvent(makeCommandEvent('--show-modal'));
|
|
79
79
|
expect(handler).toHaveBeenCalledOnce();
|
|
80
80
|
cleanup(el);
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
it('fires bds-close on close command', async () => {
|
|
83
|
+
it('fires bds-close on --close command', async () => {
|
|
84
84
|
const el = await fixture('<bds-drawer open><p>Content</p></bds-drawer>');
|
|
85
85
|
const handler = vi.fn();
|
|
86
86
|
el.addEventListener('bds-close', handler);
|
|
87
|
-
el.dispatchEvent(makeCommandEvent('close'));
|
|
87
|
+
el.dispatchEvent(makeCommandEvent('--close'));
|
|
88
88
|
expect(handler).toHaveBeenCalledOnce();
|
|
89
89
|
cleanup(el);
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
+
it('ignores the reserved built-in "show-modal"/"close" command values (never fire on custom elements)', async () => {
|
|
93
|
+
const el = await fixture('<bds-drawer><p>Content</p></bds-drawer>');
|
|
94
|
+
const openHandler = vi.fn();
|
|
95
|
+
el.addEventListener('bds-open', openHandler);
|
|
96
|
+
el.dispatchEvent(makeCommandEvent('show-modal'));
|
|
97
|
+
expect(openHandler).not.toHaveBeenCalled();
|
|
98
|
+
cleanup(el);
|
|
99
|
+
});
|
|
100
|
+
|
|
92
101
|
it('close button click fires bds-close', async () => {
|
|
93
102
|
const el = await fixture('<bds-drawer open><p>Content</p></bds-drawer>');
|
|
94
103
|
const handler = vi.fn();
|
|
@@ -110,4 +119,84 @@ describe('bds-drawer', () => {
|
|
|
110
119
|
expect(el.querySelector('p')!.textContent).toBe('Body content');
|
|
111
120
|
cleanup(el);
|
|
112
121
|
});
|
|
122
|
+
|
|
123
|
+
it('releases body scroll lock when disconnected while open', async () => {
|
|
124
|
+
const el = await fixture('<bds-drawer open><p>Content</p></bds-drawer>');
|
|
125
|
+
expect(document.body.style.overflow).toBe('hidden');
|
|
126
|
+
cleanup(el);
|
|
127
|
+
expect(document.body.style.overflow).toBe('');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('does not touch body scroll when disconnected while closed', async () => {
|
|
131
|
+
const el = await fixture('<bds-drawer><p>Content</p></bds-drawer>');
|
|
132
|
+
document.body.style.overflow = 'hidden';
|
|
133
|
+
cleanup(el);
|
|
134
|
+
expect(document.body.style.overflow).toBe('hidden');
|
|
135
|
+
document.body.style.overflow = '';
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('wires aria-labelledby to the title element by default', async () => {
|
|
139
|
+
const el = await fixture('<bds-drawer><span slot="title">Settings</span></bds-drawer>');
|
|
140
|
+
const dialog = el.shadowRoot!.querySelector('dialog')!;
|
|
141
|
+
expect(dialog.getAttribute('aria-labelledby')).toBe('title');
|
|
142
|
+
expect(dialog.hasAttribute('aria-label')).toBe(false);
|
|
143
|
+
const titleEl = el.shadowRoot!.querySelector('#title');
|
|
144
|
+
expect(titleEl).not.toBeNull();
|
|
145
|
+
cleanup(el);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('forwards a host aria-label as an override, dropping aria-labelledby', async () => {
|
|
149
|
+
const el = await fixture('<bds-drawer aria-label="Custom name"><span slot="title">Settings</span></bds-drawer>');
|
|
150
|
+
const dialog = el.shadowRoot!.querySelector('dialog')!;
|
|
151
|
+
expect(dialog.getAttribute('aria-label')).toBe('Custom name');
|
|
152
|
+
expect(dialog.hasAttribute('aria-labelledby')).toBe(false);
|
|
153
|
+
cleanup(el);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('closes when the backdrop (dialog element itself) is clicked', async () => {
|
|
157
|
+
const el = await fixture('<bds-drawer open><p>Content</p></bds-drawer>');
|
|
158
|
+
const handler = vi.fn();
|
|
159
|
+
el.addEventListener('bds-close', handler);
|
|
160
|
+
const dialog = el.shadowRoot!.querySelector('dialog')!;
|
|
161
|
+
dialog.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
162
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
163
|
+
cleanup(el);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('does not close when an inner control is clicked, including a synthetic keyboard-activation click at 0,0 (target !== dialog)', async () => {
|
|
167
|
+
// Regression test: the previous implementation compared e.clientX/clientY
|
|
168
|
+
// against the panel's bounding rect, so a keyboard-activated synthetic
|
|
169
|
+
// click (dispatched at 0,0) on an inner control was misclassified as an
|
|
170
|
+
// "outside" backdrop click and closed the drawer. Coordinates must no
|
|
171
|
+
// longer matter — only event.target identity.
|
|
172
|
+
const el = await fixture('<bds-drawer open><p>Content</p></bds-drawer>');
|
|
173
|
+
const handler = vi.fn();
|
|
174
|
+
el.addEventListener('bds-close', handler);
|
|
175
|
+
const header = el.shadowRoot!.querySelector('.header')!;
|
|
176
|
+
header.dispatchEvent(new MouseEvent('click', { bubbles: true, clientX: 0, clientY: 0 }));
|
|
177
|
+
expect(handler).not.toHaveBeenCalled();
|
|
178
|
+
cleanup(el);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('Tab focus trap treats slotted body elements as part of the trap boundary', async () => {
|
|
182
|
+
// Regression test: previously the trap only queried the shadow tree, so
|
|
183
|
+
// `all` was just [close-button] and slotted light-DOM buttons were never
|
|
184
|
+
// reachable as the wrap boundary.
|
|
185
|
+
const el = await fixture(
|
|
186
|
+
'<bds-drawer open><button id="a">A</button><button id="b">B</button></bds-drawer>',
|
|
187
|
+
) as BdsDrawer;
|
|
188
|
+
const dialog = el.shadowRoot!.querySelector('dialog')!;
|
|
189
|
+
const closeBtn = el.shadowRoot!.querySelector<HTMLButtonElement>('button.close-button')!;
|
|
190
|
+
const btnB = el.querySelector<HTMLButtonElement>('#b')!;
|
|
191
|
+
const focusSpy = vi.spyOn(btnB, 'focus');
|
|
192
|
+
// Stub shadowRoot.activeElement (jsdom doesn't implement shadow-DOM focus
|
|
193
|
+
// retargeting) to simulate focus currently sitting on the close button —
|
|
194
|
+
// the "first" stop in the merged [close-button, ...slotted] boundary list.
|
|
195
|
+
Object.defineProperty(el.shadowRoot, 'activeElement', { value: closeBtn, configurable: true });
|
|
196
|
+
const event = new KeyboardEvent('keydown', { key: 'Tab', shiftKey: true, bubbles: true, cancelable: true });
|
|
197
|
+
dialog.dispatchEvent(event);
|
|
198
|
+
// Shift+Tab from "first" must wrap to "last" — the last slotted button (#b).
|
|
199
|
+
expect(focusSpy).toHaveBeenCalled();
|
|
200
|
+
cleanup(el);
|
|
201
|
+
});
|
|
113
202
|
});
|