@boostdev/design-system-components 2.8.0 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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-OF6FFGOT.js → chunk-3AY2YKCM.js} +77 -21
- package/dist/web-components/chunk-3WAV6MDN.js +212 -0
- package/dist/web-components/{chunk-UUKSDCYS.js → chunk-47AT5KZD.js} +87 -15
- 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-QLT6MTZF.js → chunk-AIBOHNDU.js} +10 -0
- package/dist/web-components/{chunk-X3NQMBAQ.js → chunk-AP4RDUL2.js} +14 -3
- 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-ARMKC4BQ.js → chunk-JH6LQKLK.js} +77 -5
- 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-FSZRP43R.js → chunk-WFVKU4GX.js} +21 -10
- 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-ORC56MDY.js → chunk-XIZWAWMJ.js} +45 -6
- 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 +55 -8
- 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 +101 -16
- 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 +135 -22
- 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 +95 -7
- package/src/web-components/interaction/form/bds-slider.spec.ts +83 -0
- package/src/web-components/interaction/form/bds-slider.ts +154 -26
- package/src/web-components/interaction/form/bds-switch.spec.ts +68 -0
- package/src/web-components/interaction/form/bds-switch.ts +87 -20
- package/src/web-components/interaction/form/bds-textarea.spec.ts +71 -0
- package/src/web-components/interaction/form/bds-textarea.ts +108 -7
- 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 +29 -11
- 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 +109 -32
- 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 +15 -14
- 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 +10 -0
- 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 +17 -4
- 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-7YURXHTS.js +0 -147
- package/dist/web-components/chunk-A3RLT3AS.js +0 -49
- package/dist/web-components/chunk-AGKJTMJI.js +0 -56
- package/dist/web-components/chunk-BQLZ7I4G.js +0 -56
- package/dist/web-components/chunk-DZOEPVFT.js +0 -107
- package/dist/web-components/chunk-JYYRJS2D.js +0 -118
- 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
|
@@ -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
|
});
|
|
@@ -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
|
|
|
@@ -13,6 +13,7 @@ export type DrawerSide = 'left' | 'right';
|
|
|
13
13
|
* Attributes:
|
|
14
14
|
* open — boolean; controlled open state
|
|
15
15
|
* side — "left" | "right" (default: "right")
|
|
16
|
+
* aria-label — optional; overrides the default accessible name (the title slot)
|
|
16
17
|
*
|
|
17
18
|
* Slots:
|
|
18
19
|
* title — drawer title text
|
|
@@ -27,10 +28,20 @@ export type DrawerSide = 'left' | 'right';
|
|
|
27
28
|
* <span slot="title">Settings</span>
|
|
28
29
|
* <p>Drawer content</p>
|
|
29
30
|
* </bds-drawer>
|
|
30
|
-
* <button commandfor="my-drawer" command="show-modal">Open</button>
|
|
31
|
+
* <button commandfor="my-drawer" command="--show-modal">Open</button>
|
|
31
32
|
*/
|
|
32
33
|
export class BdsDrawer extends LitElement {
|
|
33
34
|
static styles = css`
|
|
35
|
+
/* Shadow DOM does not inherit the global box-sizing reset, so set it
|
|
36
|
+
here; otherwise elements with an explicit size + padding size as
|
|
37
|
+
content-box and layouts drift from the React (light-DOM) versions. */
|
|
38
|
+
:host,
|
|
39
|
+
*,
|
|
40
|
+
*::before,
|
|
41
|
+
*::after {
|
|
42
|
+
box-sizing: border-box;
|
|
43
|
+
}
|
|
44
|
+
|
|
34
45
|
:host {
|
|
35
46
|
display: contents;
|
|
36
47
|
}
|
|
@@ -59,6 +70,13 @@ export class BdsDrawer extends LitElement {
|
|
|
59
70
|
overlay var(--bds-animation_transition-duration) var(--bds-animation_easing) allow-discrete;
|
|
60
71
|
}
|
|
61
72
|
|
|
73
|
+
/* Closed native <dialog> must be display:none — the flex layout above would
|
|
74
|
+
otherwise keep it rendered (off-screen, focusable, causing overflow). The
|
|
75
|
+
display/overlay allow-discrete transitions above animate the none↔flex. */
|
|
76
|
+
.drawer:not([open]) {
|
|
77
|
+
display: none;
|
|
78
|
+
}
|
|
79
|
+
|
|
62
80
|
:host([side='left']) .drawer {
|
|
63
81
|
inset-inline: 0 auto;
|
|
64
82
|
translate: -100% 0;
|
|
@@ -84,8 +102,8 @@ export class BdsDrawer extends LitElement {
|
|
|
84
102
|
opacity: 0;
|
|
85
103
|
transition:
|
|
86
104
|
opacity var(--bds-animation_transition-duration) var(--bds-animation_easing),
|
|
87
|
-
display var(--bds-animation_transition-duration) allow-discrete,
|
|
88
|
-
overlay var(--bds-animation_transition-duration) allow-discrete;
|
|
105
|
+
display var(--bds-animation_transition-duration) var(--bds-animation_easing) allow-discrete,
|
|
106
|
+
overlay var(--bds-animation_transition-duration) var(--bds-animation_easing) allow-discrete;
|
|
89
107
|
}
|
|
90
108
|
|
|
91
109
|
.drawer[open]::backdrop {
|
|
@@ -117,8 +135,8 @@ export class BdsDrawer extends LitElement {
|
|
|
117
135
|
display: flex;
|
|
118
136
|
align-items: center;
|
|
119
137
|
justify-content: center;
|
|
120
|
-
inline-size:
|
|
121
|
-
block-size:
|
|
138
|
+
inline-size: 2.75rem;
|
|
139
|
+
block-size: 2.75rem;
|
|
122
140
|
border-radius: var(--drawer_close-radius, var(--bds-border_radius--circle));
|
|
123
141
|
cursor: pointer;
|
|
124
142
|
transition: var(--bds-animation_transition);
|
|
@@ -159,10 +177,12 @@ export class BdsDrawer extends LitElement {
|
|
|
159
177
|
static properties = {
|
|
160
178
|
open: { type: Boolean, reflect: true },
|
|
161
179
|
side: { type: String, reflect: true },
|
|
180
|
+
ariaLabel: { type: String, attribute: 'aria-label' },
|
|
162
181
|
};
|
|
163
182
|
|
|
164
183
|
declare open: boolean;
|
|
165
184
|
declare side: DrawerSide;
|
|
185
|
+
declare ariaLabel: string | null;
|
|
166
186
|
|
|
167
187
|
private _triggerEl: Element | null = null;
|
|
168
188
|
|
|
@@ -170,6 +190,7 @@ export class BdsDrawer extends LitElement {
|
|
|
170
190
|
super();
|
|
171
191
|
this.open = false;
|
|
172
192
|
this.side = 'right';
|
|
193
|
+
this.ariaLabel = null;
|
|
173
194
|
}
|
|
174
195
|
|
|
175
196
|
connectedCallback() {
|
|
@@ -180,6 +201,7 @@ export class BdsDrawer extends LitElement {
|
|
|
180
201
|
disconnectedCallback() {
|
|
181
202
|
super.disconnectedCallback();
|
|
182
203
|
this.removeEventListener('command', this._onCommand);
|
|
204
|
+
if (this.open) document.body.style.overflow = '';
|
|
183
205
|
}
|
|
184
206
|
|
|
185
207
|
updated(changed: Map<string, unknown>) {
|
|
@@ -206,8 +228,8 @@ export class BdsDrawer extends LitElement {
|
|
|
206
228
|
|
|
207
229
|
private _onCommand = (e: Event) => {
|
|
208
230
|
const command = (e as CommandEvent).command;
|
|
209
|
-
if (command === 'show-modal') this._openDrawer();
|
|
210
|
-
else if (command === 'close') this._closeDrawer();
|
|
231
|
+
if (command === '--show-modal') this._openDrawer();
|
|
232
|
+
else if (command === '--close') this._closeDrawer();
|
|
211
233
|
};
|
|
212
234
|
|
|
213
235
|
private _openDrawer() {
|
|
@@ -223,14 +245,12 @@ export class BdsDrawer extends LitElement {
|
|
|
223
245
|
this.dispatchEvent(new CustomEvent('bds-close', { bubbles: true, composed: true }));
|
|
224
246
|
}
|
|
225
247
|
|
|
248
|
+
// Close on backdrop click. The dialog element's own box is only the visible
|
|
249
|
+
// panel — clicking the ::backdrop dispatches with e.target === the dialog
|
|
250
|
+
// itself, so this correctly ignores clicks (including keyboard-activated
|
|
251
|
+
// synthetic clicks at 0,0) on controls inside the panel.
|
|
226
252
|
private _handleBackdropClick(e: MouseEvent) {
|
|
227
|
-
|
|
228
|
-
if (!dialog) return;
|
|
229
|
-
const rect = dialog.getBoundingClientRect();
|
|
230
|
-
const outside =
|
|
231
|
-
e.clientX < rect.left || e.clientX > rect.right ||
|
|
232
|
-
e.clientY < rect.top || e.clientY > rect.bottom;
|
|
233
|
-
if (outside) this._closeDrawer();
|
|
253
|
+
if (e.target === this._dialog) this._closeDrawer();
|
|
234
254
|
}
|
|
235
255
|
|
|
236
256
|
private _handleCancel(e: Event) {
|
|
@@ -243,13 +263,24 @@ export class BdsDrawer extends LitElement {
|
|
|
243
263
|
const dialog = this._dialog;
|
|
244
264
|
if (!dialog) return;
|
|
245
265
|
const focusable = Array.from(dialog.querySelectorAll<HTMLElement>(FOCUSABLE));
|
|
246
|
-
|
|
247
|
-
const
|
|
248
|
-
const
|
|
266
|
+
// Also include slotted elements from light DOM via the title + default slots
|
|
267
|
+
const slots = Array.from(dialog.querySelectorAll<HTMLSlotElement>('slot'));
|
|
268
|
+
const slottedFocusable = slots.flatMap(slot =>
|
|
269
|
+
slot.assignedElements({ flatten: true })
|
|
270
|
+
.flatMap(el => [
|
|
271
|
+
...(el.matches(FOCUSABLE) ? [el as HTMLElement] : []),
|
|
272
|
+
...Array.from(el.querySelectorAll<HTMLElement>(FOCUSABLE)),
|
|
273
|
+
]),
|
|
274
|
+
);
|
|
275
|
+
const all = [...focusable, ...slottedFocusable];
|
|
276
|
+
if (all.length === 0) return;
|
|
277
|
+
const first = all[0];
|
|
278
|
+
const last = all[all.length - 1];
|
|
279
|
+
const active = this.shadowRoot?.activeElement ?? document.activeElement;
|
|
249
280
|
if (e.shiftKey) {
|
|
250
|
-
if (
|
|
281
|
+
if (active === first) { e.preventDefault(); last.focus(); }
|
|
251
282
|
} else {
|
|
252
|
-
if (
|
|
283
|
+
if (active === last) { e.preventDefault(); first.focus(); }
|
|
253
284
|
}
|
|
254
285
|
}
|
|
255
286
|
|
|
@@ -258,12 +289,14 @@ export class BdsDrawer extends LitElement {
|
|
|
258
289
|
<dialog
|
|
259
290
|
class="drawer"
|
|
260
291
|
aria-modal="true"
|
|
292
|
+
aria-label=${this.ariaLabel ?? nothing}
|
|
293
|
+
aria-labelledby=${this.ariaLabel ? nothing : 'title'}
|
|
261
294
|
@click=${this._handleBackdropClick}
|
|
262
295
|
@cancel=${this._handleCancel}
|
|
263
296
|
@keydown=${this._handleKeydown}
|
|
264
297
|
>
|
|
265
298
|
<div class="header">
|
|
266
|
-
<span class="title"><slot name="title"></slot></span>
|
|
299
|
+
<span class="title" id="title"><slot name="title"></slot></span>
|
|
267
300
|
<button
|
|
268
301
|
type="button"
|
|
269
302
|
class="close-button"
|
|
@@ -19,6 +19,16 @@ import { LitElement, css, html } from 'lit';
|
|
|
19
19
|
*/
|
|
20
20
|
export class BdsDropdownMenuItem extends LitElement {
|
|
21
21
|
static styles = css`
|
|
22
|
+
/* Shadow DOM does not inherit the global box-sizing reset, so set it
|
|
23
|
+
here; otherwise elements with an explicit size + padding size as
|
|
24
|
+
content-box and layouts drift from the React (light-DOM) versions. */
|
|
25
|
+
:host,
|
|
26
|
+
*,
|
|
27
|
+
*::before,
|
|
28
|
+
*::after {
|
|
29
|
+
box-sizing: border-box;
|
|
30
|
+
}
|
|
31
|
+
|
|
22
32
|
:host {
|
|
23
33
|
display: block;
|
|
24
34
|
}
|
|
@@ -51,7 +61,8 @@ export class BdsDropdownMenuItem extends LitElement {
|
|
|
51
61
|
|
|
52
62
|
@media (hover: hover) and (pointer: fine) {
|
|
53
63
|
.item:hover {
|
|
54
|
-
background-color: var(--bds-color_bg--subtle);
|
|
64
|
+
background-color: var(--dropdown_item-bg--hover, var(--bds-color_bg--subtle));
|
|
65
|
+
color: var(--dropdown_item-color--hover, var(--bds-color_interactive_on-bg));
|
|
55
66
|
}
|
|
56
67
|
|
|
57
68
|
:host([destructive]) .item:hover {
|