@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LitElement, css, html } from 'lit';
|
|
1
|
+
import { LitElement, css, html, nothing } from 'lit';
|
|
2
2
|
|
|
3
3
|
export type PopoverPlacement = 'bottom' | 'top' | 'left' | 'right';
|
|
4
4
|
|
|
@@ -10,11 +10,14 @@ export type PopoverPlacement = 'bottom' | 'top' | 'left' | 'right';
|
|
|
10
10
|
* overflow the viewport (`@position-try` fallbacks).
|
|
11
11
|
*
|
|
12
12
|
* Attributes:
|
|
13
|
-
* placement
|
|
14
|
-
* open
|
|
13
|
+
* placement — "bottom" (default) | "top" | "left" | "right"
|
|
14
|
+
* open — boolean; reflects whether the panel is visible
|
|
15
|
+
* aria-label — accessible name for the panel; when present the panel gets
|
|
16
|
+
* `role="region"` (mirrors the React implementation)
|
|
15
17
|
*
|
|
16
18
|
* Slots:
|
|
17
|
-
* trigger — the element that opens/closes the panel on click
|
|
19
|
+
* trigger — the element that opens/closes the panel on click. Receives
|
|
20
|
+
* `aria-haspopup`, `aria-controls` and `aria-expanded` wiring.
|
|
18
21
|
* (default) — panel content
|
|
19
22
|
*
|
|
20
23
|
* Events:
|
|
@@ -29,6 +32,16 @@ export type PopoverPlacement = 'bottom' | 'top' | 'left' | 'right';
|
|
|
29
32
|
*/
|
|
30
33
|
export class BdsPopover extends LitElement {
|
|
31
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
|
+
|
|
32
45
|
:host {
|
|
33
46
|
display: inline-flex;
|
|
34
47
|
position: relative;
|
|
@@ -39,19 +52,23 @@ export class BdsPopover extends LitElement {
|
|
|
39
52
|
gets its own unique name without colliding with siblings. */
|
|
40
53
|
.wrapper {
|
|
41
54
|
display: inline-flex;
|
|
42
|
-
anchor-name: var(--
|
|
55
|
+
anchor-name: var(--popover-anchor);
|
|
43
56
|
}
|
|
44
57
|
|
|
45
58
|
.panel {
|
|
46
59
|
display: none;
|
|
47
|
-
|
|
48
|
-
position
|
|
60
|
+
|
|
61
|
+
/* position: fixed (not absolute) — containing block is the viewport,
|
|
62
|
+
so the panel escapes ancestor overflow:hidden/scroll clipping and
|
|
63
|
+
stacking contexts, matching the React implementation. */
|
|
64
|
+
position: fixed;
|
|
65
|
+
position-anchor: var(--popover-anchor);
|
|
49
66
|
margin: 0;
|
|
50
|
-
overflow-
|
|
67
|
+
overflow-block: auto;
|
|
51
68
|
z-index: var(--popover_z-index, 100);
|
|
52
|
-
min-
|
|
53
|
-
max-
|
|
54
|
-
max-
|
|
69
|
+
min-inline-size: 12rem;
|
|
70
|
+
max-inline-size: var(--popover_max-width, 20rem);
|
|
71
|
+
max-block-size: var(--popover_max-height, 80dvh);
|
|
55
72
|
padding: var(--bds-space_m);
|
|
56
73
|
border: var(--popover_border, none);
|
|
57
74
|
--bdc_color: currentcolor;
|
|
@@ -72,86 +89,94 @@ export class BdsPopover extends LitElement {
|
|
|
72
89
|
.panel[data-placement='bottom'] {
|
|
73
90
|
top: anchor(bottom);
|
|
74
91
|
left: anchor(left);
|
|
75
|
-
margin-
|
|
76
|
-
position-try-fallbacks: --
|
|
92
|
+
margin-block-start: var(--bds-space_xs, 8px);
|
|
93
|
+
position-try-fallbacks: --popover-top, --popover-right, --popover-left;
|
|
77
94
|
}
|
|
78
95
|
|
|
79
96
|
.panel[data-placement='top'] {
|
|
80
97
|
bottom: anchor(top);
|
|
81
98
|
left: anchor(left);
|
|
82
|
-
margin-
|
|
83
|
-
position-try-fallbacks: --
|
|
99
|
+
margin-block-end: var(--bds-space_xs, 8px);
|
|
100
|
+
position-try-fallbacks: --popover-bottom, --popover-right, --popover-left;
|
|
84
101
|
}
|
|
85
102
|
|
|
86
103
|
.panel[data-placement='right'] {
|
|
87
104
|
top: anchor(top);
|
|
88
105
|
left: anchor(right);
|
|
89
|
-
margin-
|
|
90
|
-
position-try-fallbacks: --
|
|
106
|
+
margin-inline-start: var(--bds-space_xs, 8px);
|
|
107
|
+
position-try-fallbacks: --popover-left, --popover-bottom, --popover-top;
|
|
91
108
|
}
|
|
92
109
|
|
|
93
110
|
.panel[data-placement='left'] {
|
|
94
111
|
top: anchor(top);
|
|
95
112
|
right: anchor(left);
|
|
96
|
-
margin-
|
|
97
|
-
position-try-fallbacks: --
|
|
113
|
+
margin-inline-end: var(--bds-space_xs, 8px);
|
|
114
|
+
position-try-fallbacks: --popover-right, --popover-bottom, --popover-top;
|
|
98
115
|
}
|
|
99
116
|
|
|
100
117
|
/* Fallback placements */
|
|
101
118
|
|
|
102
|
-
@position-try --
|
|
119
|
+
@position-try --popover-bottom {
|
|
103
120
|
top: anchor(bottom);
|
|
104
121
|
right: unset;
|
|
105
122
|
bottom: unset;
|
|
106
123
|
left: anchor(left);
|
|
107
124
|
margin: 0;
|
|
108
|
-
margin-
|
|
125
|
+
margin-block-start: var(--bds-space_xs, 8px);
|
|
109
126
|
}
|
|
110
127
|
|
|
111
|
-
@position-try --
|
|
128
|
+
@position-try --popover-top {
|
|
112
129
|
top: unset;
|
|
113
130
|
right: unset;
|
|
114
131
|
bottom: anchor(top);
|
|
115
132
|
left: anchor(left);
|
|
116
133
|
margin: 0;
|
|
117
|
-
margin-
|
|
134
|
+
margin-block-end: var(--bds-space_xs, 8px);
|
|
118
135
|
}
|
|
119
136
|
|
|
120
|
-
@position-try --
|
|
137
|
+
@position-try --popover-right {
|
|
121
138
|
top: anchor(top);
|
|
122
139
|
right: unset;
|
|
123
140
|
bottom: unset;
|
|
124
141
|
left: anchor(right);
|
|
125
142
|
margin: 0;
|
|
126
|
-
margin-
|
|
143
|
+
margin-inline-start: var(--bds-space_xs, 8px);
|
|
127
144
|
}
|
|
128
145
|
|
|
129
|
-
@position-try --
|
|
146
|
+
@position-try --popover-left {
|
|
130
147
|
top: anchor(top);
|
|
131
148
|
right: anchor(left);
|
|
132
149
|
bottom: unset;
|
|
133
150
|
left: unset;
|
|
134
151
|
margin: 0;
|
|
135
|
-
margin-
|
|
152
|
+
margin-inline-end: var(--bds-space_xs, 8px);
|
|
136
153
|
}
|
|
137
154
|
`;
|
|
138
155
|
|
|
139
156
|
static properties = {
|
|
140
157
|
placement: { type: String, reflect: true },
|
|
141
158
|
open: { type: Boolean, reflect: true },
|
|
159
|
+
ariaLabel: { type: String, attribute: 'aria-label' },
|
|
142
160
|
};
|
|
143
161
|
|
|
144
162
|
declare placement: PopoverPlacement;
|
|
145
163
|
declare open: boolean;
|
|
164
|
+
declare ariaLabel: string | null;
|
|
146
165
|
|
|
147
166
|
private _anchorName: string;
|
|
167
|
+
private _panelId: string;
|
|
168
|
+
private _triggerEl: HTMLElement | null = null;
|
|
148
169
|
|
|
149
170
|
constructor() {
|
|
150
171
|
super();
|
|
151
172
|
this.placement = 'bottom';
|
|
152
173
|
this.open = false;
|
|
174
|
+
this.ariaLabel = null;
|
|
153
175
|
const uid = Math.random().toString(36).slice(2, 8);
|
|
154
|
-
|
|
176
|
+
// Non-`--bds-` prefixed — these are internal coordination idents, not
|
|
177
|
+
// foundation-owned tokens, so they must not squat the `--bds-` namespace.
|
|
178
|
+
this._anchorName = `--popover-${uid}`;
|
|
179
|
+
this._panelId = `bds-popover-panel-${uid}`;
|
|
155
180
|
}
|
|
156
181
|
|
|
157
182
|
connectedCallback() {
|
|
@@ -159,7 +184,7 @@ export class BdsPopover extends LitElement {
|
|
|
159
184
|
// Inject the unique anchor-name as a CSS custom property so both
|
|
160
185
|
// `.wrapper` (anchor-name) and `.panel` (position-anchor) reference
|
|
161
186
|
// the same value without hard-coding it in the shared static styles.
|
|
162
|
-
this.style.setProperty('--
|
|
187
|
+
this.style.setProperty('--popover-anchor', this._anchorName);
|
|
163
188
|
document.addEventListener('keydown', this._onKeydown);
|
|
164
189
|
document.addEventListener('mousedown', this._onOutsideClick);
|
|
165
190
|
// Invoker Commands API — host is in light DOM so commandfor can reference its id.
|
|
@@ -199,25 +224,51 @@ export class BdsPopover extends LitElement {
|
|
|
199
224
|
private _open() {
|
|
200
225
|
if (this.open) return;
|
|
201
226
|
this.open = true;
|
|
227
|
+
this._triggerEl?.setAttribute('aria-expanded', 'true');
|
|
202
228
|
this.dispatchEvent(new CustomEvent('bds-open', { bubbles: true, composed: true }));
|
|
203
229
|
}
|
|
204
230
|
|
|
205
231
|
private _close() {
|
|
206
232
|
if (!this.open) return;
|
|
207
233
|
this.open = false;
|
|
234
|
+
this._triggerEl?.setAttribute('aria-expanded', 'false');
|
|
208
235
|
this.dispatchEvent(new CustomEvent('bds-close', { bubbles: true, composed: true }));
|
|
236
|
+
// Restore focus to the trigger only if it was inside this popover (panel
|
|
237
|
+
// content or the trigger itself) — an outside click that closes the
|
|
238
|
+
// panel has already moved focus elsewhere and should not be overridden.
|
|
239
|
+
if (this.contains(document.activeElement)) {
|
|
240
|
+
this._triggerEl?.focus();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Track the slotted trigger so aria-expanded/haspopup/controls can be kept
|
|
245
|
+
// in sync and focus can be restored on close (mirrors the React
|
|
246
|
+
// cloneElement wiring and bds-dropdown-menu's trigger-tracking pattern).
|
|
247
|
+
private _onTriggerSlotChange(e: Event) {
|
|
248
|
+
const slot = e.target as HTMLSlotElement;
|
|
249
|
+
this._triggerEl = (slot.assignedElements()[0] as HTMLElement) ?? null;
|
|
250
|
+
if (this._triggerEl) {
|
|
251
|
+
this._triggerEl.setAttribute('aria-haspopup', 'true');
|
|
252
|
+
this._triggerEl.setAttribute('aria-controls', this._panelId);
|
|
253
|
+
this._triggerEl.setAttribute('aria-expanded', String(this.open));
|
|
254
|
+
}
|
|
209
255
|
}
|
|
210
256
|
|
|
211
257
|
render() {
|
|
212
258
|
return html`
|
|
213
259
|
<span class="wrapper">
|
|
214
|
-
<slot
|
|
260
|
+
<slot
|
|
261
|
+
name="trigger"
|
|
262
|
+
@click=${this._toggle}
|
|
263
|
+
@slotchange=${this._onTriggerSlotChange}
|
|
264
|
+
></slot>
|
|
215
265
|
</span>
|
|
216
266
|
<div
|
|
217
267
|
class="panel ${this.open ? 'open' : ''}"
|
|
218
268
|
data-placement=${this.placement}
|
|
219
|
-
|
|
220
|
-
|
|
269
|
+
id=${this._panelId}
|
|
270
|
+
role=${this.ariaLabel ? 'region' : nothing}
|
|
271
|
+
aria-label=${this.ariaLabel ?? nothing}
|
|
221
272
|
>
|
|
222
273
|
<slot></slot>
|
|
223
274
|
</div>
|
|
@@ -39,4 +39,22 @@ describe('bds-skip-link', () => {
|
|
|
39
39
|
expect(el.textContent?.trim()).toBe('Go to main');
|
|
40
40
|
cleanup(el);
|
|
41
41
|
});
|
|
42
|
+
|
|
43
|
+
it('uses a themeable z-index token with a fallback instead of a hardcoded value', () => {
|
|
44
|
+
const cssText = BdsSkipLink.styles.cssText;
|
|
45
|
+
expect(cssText).toContain('z-index: var(--skip-link_z-index, var(--bds-z-index_xl))');
|
|
46
|
+
expect(cssText).not.toContain('z-index: 9999');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('exposes the --skip-link_border hook and the bdc inset focus-border chain', () => {
|
|
50
|
+
const cssText = BdsSkipLink.styles.cssText;
|
|
51
|
+
expect(cssText).toContain('border: var(--skip-link_border, none)');
|
|
52
|
+
expect(cssText).toMatch(/box-shadow:\s*inset 0 0 0 var\(--bdc-outline_width\) var\(--bdc_color\)/);
|
|
53
|
+
expect(cssText).toContain('var(--skip-link_shadow, var(--bdc-outline_shadow))');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('guards the slide-in transition with prefers-reduced-motion', () => {
|
|
57
|
+
const cssText = BdsSkipLink.styles.cssText;
|
|
58
|
+
expect(cssText).toMatch(/@media \(prefers-reduced-motion: reduce\)\s*{\s*\.skip-link\s*{\s*transition:\s*none;/);
|
|
59
|
+
});
|
|
42
60
|
});
|
|
@@ -17,24 +17,39 @@ import { LitElement, css, html } from 'lit';
|
|
|
17
17
|
*/
|
|
18
18
|
export class BdsSkipLink extends LitElement {
|
|
19
19
|
static styles = css`
|
|
20
|
+
/* Shadow DOM does not inherit the global box-sizing reset, so set it
|
|
21
|
+
here; otherwise elements with an explicit size + padding size as
|
|
22
|
+
content-box and layouts drift from the React (light-DOM) versions. */
|
|
23
|
+
:host,
|
|
24
|
+
*,
|
|
25
|
+
*::before,
|
|
26
|
+
*::after {
|
|
27
|
+
box-sizing: border-box;
|
|
28
|
+
}
|
|
29
|
+
|
|
20
30
|
:host {
|
|
21
31
|
display: block;
|
|
22
32
|
}
|
|
23
33
|
|
|
24
34
|
.skip-link {
|
|
25
35
|
position: absolute;
|
|
26
|
-
inset-block-start: var(--bds-space_s);
|
|
27
|
-
inset-inline-start: var(--bds-space_s);
|
|
28
|
-
z-index:
|
|
29
|
-
padding: var(--bds-space_xs) var(--bds-space_m);
|
|
36
|
+
inset-block-start: var(--skip-link_inset, var(--bds-space_s));
|
|
37
|
+
inset-inline-start: var(--skip-link_inset, var(--bds-space_s));
|
|
38
|
+
z-index: var(--skip-link_z-index, var(--bds-z-index_xl));
|
|
39
|
+
padding: var(--skip-link_padding, var(--bds-space_xs) var(--bds-space_m));
|
|
30
40
|
background-color: var(--bds-color_bg);
|
|
31
41
|
color: var(--bds-color_on-bg);
|
|
32
|
-
border-radius: var(--bds-border_radius--s);
|
|
42
|
+
border-radius: var(--skip-link_radius, var(--bds-border_radius--s));
|
|
33
43
|
font-weight: var(--bds-font_weight--semibold);
|
|
34
|
-
font-size: var(--bds-font_size--body);
|
|
44
|
+
font-size: var(--skip-link_font-size, var(--bds-font_size--body));
|
|
35
45
|
text-decoration: none;
|
|
36
|
-
|
|
37
|
-
|
|
46
|
+
|
|
47
|
+
--bdc_color: var(--color_focus, var(--bds-color_interactive));
|
|
48
|
+
|
|
49
|
+
border: var(--skip-link_border, none);
|
|
50
|
+
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color),
|
|
51
|
+
var(--skip-link_shadow, var(--bdc-outline_shadow));
|
|
52
|
+
transform: translateY(calc(-100% - var(--skip-link_inset, var(--bds-space_s))));
|
|
38
53
|
transition: transform var(--bds-animation_transition-duration) var(--bds-animation_easing);
|
|
39
54
|
}
|
|
40
55
|
|
|
@@ -43,6 +58,12 @@ export class BdsSkipLink extends LitElement {
|
|
|
43
58
|
outline: var(--bds-outline_default);
|
|
44
59
|
outline-offset: var(--bds-outline_offset);
|
|
45
60
|
}
|
|
61
|
+
|
|
62
|
+
@media (prefers-reduced-motion: reduce) {
|
|
63
|
+
.skip-link {
|
|
64
|
+
transition: none;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
46
67
|
`;
|
|
47
68
|
|
|
48
69
|
static properties = {
|
|
@@ -14,6 +14,16 @@ import { LitElement, css, html } from 'lit';
|
|
|
14
14
|
*/
|
|
15
15
|
export class BdsTabPanel extends LitElement {
|
|
16
16
|
static styles = css`
|
|
17
|
+
/* Shadow DOM does not inherit the global box-sizing reset, so set it
|
|
18
|
+
here; otherwise elements with an explicit size + padding size as
|
|
19
|
+
content-box and layouts drift from the React (light-DOM) versions. */
|
|
20
|
+
:host,
|
|
21
|
+
*,
|
|
22
|
+
*::before,
|
|
23
|
+
*::after {
|
|
24
|
+
box-sizing: border-box;
|
|
25
|
+
}
|
|
26
|
+
|
|
17
27
|
:host {
|
|
18
28
|
display: block;
|
|
19
29
|
padding-block-start: var(--bds-space_m);
|
|
@@ -68,4 +68,29 @@ describe('bds-tab', () => {
|
|
|
68
68
|
expect(btn.hasAttribute('disabled')).toBe(true);
|
|
69
69
|
cleanup(el);
|
|
70
70
|
});
|
|
71
|
+
|
|
72
|
+
it('lets the public --tab_color/--tab_border-color tokens win over selected/hover-state defaults', () => {
|
|
73
|
+
const cssText = BdsTab.styles.cssText;
|
|
74
|
+
expect(cssText).toMatch(
|
|
75
|
+
/\.tab\s*{[^}]*color:\s*var\(--tab_color,\s*var\(--tab_color--state,\s*var\(--bds-color_on-bg\)\)\)/,
|
|
76
|
+
);
|
|
77
|
+
expect(cssText).toMatch(
|
|
78
|
+
/\.tab\s*{[^}]*border-block-end:\s*2px solid var\(--tab_border-color,\s*var\(--tab_border-color--state,\s*transparent\)\)/,
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('has the selected/hover rules write only to the internal --tab_*--state slots, not the public tokens', () => {
|
|
83
|
+
const cssText = BdsTab.styles.cssText;
|
|
84
|
+
expect(cssText).not.toMatch(/:host\(\[selected\]\)\s*\.tab\s*{[^}]*--tab_color:/);
|
|
85
|
+
expect(cssText).not.toMatch(/:host\(\[selected\]\)\s*\.tab\s*{[^}]*--tab_border-color:/);
|
|
86
|
+
expect(cssText).toMatch(
|
|
87
|
+
/:host\(\[selected\]\)\s*\.tab\s*{[^}]*--tab_color--state:\s*var\(--tab_color--active,/,
|
|
88
|
+
);
|
|
89
|
+
expect(cssText).toMatch(
|
|
90
|
+
/:host\(\[selected\]\)\s*\.tab\s*{[^}]*--tab_border-color--state:\s*var\(--tab_border-color--active,/,
|
|
91
|
+
);
|
|
92
|
+
expect(cssText).toMatch(
|
|
93
|
+
/--tab_color--state:\s*var\(--tab_color--hover,/,
|
|
94
|
+
);
|
|
95
|
+
});
|
|
71
96
|
});
|
|
@@ -17,6 +17,16 @@ import { LitElement, css, html } from 'lit';
|
|
|
17
17
|
*/
|
|
18
18
|
export class BdsTab extends LitElement {
|
|
19
19
|
static styles = css`
|
|
20
|
+
/* Shadow DOM does not inherit the global box-sizing reset, so set it
|
|
21
|
+
here; otherwise elements with an explicit size + padding size as
|
|
22
|
+
content-box and layouts drift from the React (light-DOM) versions. */
|
|
23
|
+
:host,
|
|
24
|
+
*,
|
|
25
|
+
*::before,
|
|
26
|
+
*::after {
|
|
27
|
+
box-sizing: border-box;
|
|
28
|
+
}
|
|
29
|
+
|
|
20
30
|
:host {
|
|
21
31
|
display: inline-flex;
|
|
22
32
|
}
|
|
@@ -29,8 +39,13 @@ export class BdsTab extends LitElement {
|
|
|
29
39
|
font-family: var(--bds-font_family--body);
|
|
30
40
|
font-size: var(--bds-font_size--body);
|
|
31
41
|
font-weight: var(--bds-font_weight--semibold);
|
|
32
|
-
|
|
33
|
-
|
|
42
|
+
|
|
43
|
+
/* Layered cascade: public overrides (--tab_color, --tab_border-color) win over
|
|
44
|
+
per-state defaults. Active/hover write to the inner --tab_*--state slot —
|
|
45
|
+
mirrors the React Tabs.module.css pattern so a consumer's --tab_color
|
|
46
|
+
override is never shadowed by the selected/hover rules below. */
|
|
47
|
+
color: var(--tab_color, var(--tab_color--state, var(--bds-color_on-bg)));
|
|
48
|
+
border-block-end: 2px solid var(--tab_border-color, var(--tab_border-color--state, transparent));
|
|
34
49
|
margin-block-end: -1px;
|
|
35
50
|
cursor: pointer;
|
|
36
51
|
transition: var(--bds-animation_transition);
|
|
@@ -38,8 +53,8 @@ export class BdsTab extends LitElement {
|
|
|
38
53
|
}
|
|
39
54
|
|
|
40
55
|
:host([selected]) .tab {
|
|
41
|
-
--tab_color: var(--bds-color_interactive_on-bg);
|
|
42
|
-
--tab_border-color: var(--bds-color_interactive);
|
|
56
|
+
--tab_color--state: var(--tab_color--active, var(--bds-color_interactive_on-bg));
|
|
57
|
+
--tab_border-color--state: var(--tab_border-color--active, var(--bds-color_interactive));
|
|
43
58
|
}
|
|
44
59
|
|
|
45
60
|
.tab:disabled {
|
|
@@ -55,7 +70,7 @@ export class BdsTab extends LitElement {
|
|
|
55
70
|
|
|
56
71
|
@media (hover: hover) and (pointer: fine) {
|
|
57
72
|
.tab:not(:disabled, [aria-selected='true']):hover {
|
|
58
|
-
--tab_color: var(--bds-color_interactive_on-bg);
|
|
73
|
+
--tab_color--state: var(--tab_color--hover, var(--bds-color_interactive_on-bg));
|
|
59
74
|
}
|
|
60
75
|
}
|
|
61
76
|
`;
|
|
@@ -36,6 +36,23 @@ describe('bds-tabs', () => {
|
|
|
36
36
|
cleanup(el);
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
+
it('does not select a disabled first tab — activates the first enabled tab instead', async () => {
|
|
40
|
+
const el = await fixture(`
|
|
41
|
+
<bds-tabs>
|
|
42
|
+
<bds-tab slot="tab" disabled>Tab 1</bds-tab>
|
|
43
|
+
<bds-tab slot="tab">Tab 2</bds-tab>
|
|
44
|
+
<bds-tab-panel slot="panel">Panel 1</bds-tab-panel>
|
|
45
|
+
<bds-tab-panel slot="panel">Panel 2</bds-tab-panel>
|
|
46
|
+
</bds-tabs>
|
|
47
|
+
`);
|
|
48
|
+
// Wait for deferred _applyState
|
|
49
|
+
await Promise.resolve();
|
|
50
|
+
const tabs = [...el.querySelectorAll<BdsTab>('bds-tab')];
|
|
51
|
+
expect(tabs[0].selected).toBe(false);
|
|
52
|
+
expect(tabs[1].selected).toBe(true);
|
|
53
|
+
cleanup(el);
|
|
54
|
+
});
|
|
55
|
+
|
|
39
56
|
it('first panel is visible, others are hidden by default', async () => {
|
|
40
57
|
const el = await fixture(html);
|
|
41
58
|
await Promise.resolve();
|
|
@@ -77,9 +94,10 @@ describe('bds-tabs', () => {
|
|
|
77
94
|
it('ArrowRight moves to next enabled tab', async () => {
|
|
78
95
|
const el = await fixture(html);
|
|
79
96
|
await Promise.resolve();
|
|
80
|
-
el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
|
|
81
|
-
await Promise.resolve();
|
|
82
97
|
const tabs = [...el.querySelectorAll<BdsTab>('bds-tab')];
|
|
98
|
+
// Real usage: the keydown originates from the focused (currently active) tab.
|
|
99
|
+
tabs[0].dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
|
|
100
|
+
await Promise.resolve();
|
|
83
101
|
expect(tabs[1].selected).toBe(true);
|
|
84
102
|
cleanup(el);
|
|
85
103
|
});
|
|
@@ -89,7 +107,7 @@ describe('bds-tabs', () => {
|
|
|
89
107
|
await Promise.resolve();
|
|
90
108
|
const tabs = [...el.querySelectorAll<BdsTab>('bds-tab')];
|
|
91
109
|
tabs[2].disabled = true; // ensure disabled is set (Lit property may not reflect from HTML attribute in jsdom)
|
|
92
|
-
|
|
110
|
+
tabs[0].dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft', bubbles: true }));
|
|
93
111
|
// disabled tab is skipped; enabled tabs are 0 and 1 → wraps to last enabled (index 1)
|
|
94
112
|
expect(tabs[1].selected).toBe(true);
|
|
95
113
|
cleanup(el);
|
|
@@ -102,7 +120,7 @@ describe('bds-tabs', () => {
|
|
|
102
120
|
await Promise.all(tabs.map(t => t.updateComplete));
|
|
103
121
|
// Navigate to tab 1 first
|
|
104
122
|
tabs[1].dispatchEvent(new CustomEvent('bds-tab-select', { bubbles: true, composed: true }));
|
|
105
|
-
|
|
123
|
+
tabs[1].dispatchEvent(new KeyboardEvent('keydown', { key: 'Home', bubbles: true }));
|
|
106
124
|
expect(tabs[0].selected).toBe(true);
|
|
107
125
|
cleanup(el);
|
|
108
126
|
});
|
|
@@ -112,9 +130,78 @@ describe('bds-tabs', () => {
|
|
|
112
130
|
await Promise.resolve();
|
|
113
131
|
const tabs = [...el.querySelectorAll<BdsTab>('bds-tab')];
|
|
114
132
|
tabs[2].disabled = true; // ensure disabled is set
|
|
115
|
-
|
|
133
|
+
tabs[0].dispatchEvent(new KeyboardEvent('keydown', { key: 'End', bubbles: true }));
|
|
116
134
|
// Last enabled tab is index 1 (tab 3 is disabled)
|
|
117
135
|
expect(tabs[1].selected).toBe(true);
|
|
118
136
|
cleanup(el);
|
|
119
137
|
});
|
|
138
|
+
|
|
139
|
+
it('does not hijack Arrow/Home/End keys typed outside a <bds-tab> (e.g. host-level dispatch)', async () => {
|
|
140
|
+
const el = await fixture(html);
|
|
141
|
+
await Promise.resolve();
|
|
142
|
+
const tabs = [...el.querySelectorAll<BdsTab>('bds-tab')];
|
|
143
|
+
// Dispatched directly on the <bds-tabs> host — not on a <bds-tab> — must be ignored.
|
|
144
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
|
|
145
|
+
await Promise.resolve();
|
|
146
|
+
expect(tabs[0].selected).toBe(true);
|
|
147
|
+
expect(tabs[1].selected).toBe(false);
|
|
148
|
+
cleanup(el);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('does not hijack ArrowLeft pressed inside a tab-panel input (caret movement stays with the input)', async () => {
|
|
152
|
+
const el = await fixture(`
|
|
153
|
+
<bds-tabs>
|
|
154
|
+
<bds-tab slot="tab">Tab 1</bds-tab>
|
|
155
|
+
<bds-tab slot="tab">Tab 2</bds-tab>
|
|
156
|
+
<bds-tab-panel slot="panel"><input type="text" /></bds-tab-panel>
|
|
157
|
+
<bds-tab-panel slot="panel">Panel 2</bds-tab-panel>
|
|
158
|
+
</bds-tabs>
|
|
159
|
+
`);
|
|
160
|
+
await Promise.resolve();
|
|
161
|
+
const tabs = [...el.querySelectorAll<BdsTab>('bds-tab')];
|
|
162
|
+
const input = el.querySelector('input')!;
|
|
163
|
+
input.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft', bubbles: true }));
|
|
164
|
+
await Promise.resolve();
|
|
165
|
+
expect(tabs[0].selected).toBe(true);
|
|
166
|
+
expect(tabs[1].selected).toBe(false);
|
|
167
|
+
cleanup(el);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('wires role/id/aria-controls on tabs and role/id/aria-labelledby on panels', async () => {
|
|
171
|
+
const el = await fixture(html);
|
|
172
|
+
await Promise.resolve();
|
|
173
|
+
const tabs = [...el.querySelectorAll<BdsTab>('bds-tab')];
|
|
174
|
+
const panels = [...el.querySelectorAll<BdsTabPanel>('bds-tab-panel')];
|
|
175
|
+
|
|
176
|
+
tabs.forEach((tab, i) => {
|
|
177
|
+
expect(tab.getAttribute('role')).toBe('tab');
|
|
178
|
+
expect(tab.id).toBeTruthy();
|
|
179
|
+
expect(tab.getAttribute('aria-controls')).toBe(panels[i].id);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
panels.forEach((panel, i) => {
|
|
183
|
+
expect(panel.getAttribute('role')).toBe('tabpanel');
|
|
184
|
+
expect(panel.id).toBeTruthy();
|
|
185
|
+
expect(panel.getAttribute('aria-labelledby')).toBe(tabs[i].id);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
cleanup(el);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('preserves a consumer-supplied id instead of overwriting it', async () => {
|
|
192
|
+
const el = await fixture(`
|
|
193
|
+
<bds-tabs>
|
|
194
|
+
<bds-tab slot="tab" id="custom-tab-id">Tab 1</bds-tab>
|
|
195
|
+
<bds-tab-panel slot="panel" id="custom-panel-id">Panel 1</bds-tab-panel>
|
|
196
|
+
</bds-tabs>
|
|
197
|
+
`);
|
|
198
|
+
await Promise.resolve();
|
|
199
|
+
const tab = el.querySelector<BdsTab>('bds-tab')!;
|
|
200
|
+
const panel = el.querySelector<BdsTabPanel>('bds-tab-panel')!;
|
|
201
|
+
expect(tab.id).toBe('custom-tab-id');
|
|
202
|
+
expect(panel.id).toBe('custom-panel-id');
|
|
203
|
+
expect(tab.getAttribute('aria-controls')).toBe('custom-panel-id');
|
|
204
|
+
expect(panel.getAttribute('aria-labelledby')).toBe('custom-tab-id');
|
|
205
|
+
cleanup(el);
|
|
206
|
+
});
|
|
120
207
|
});
|
|
@@ -26,6 +26,16 @@ import type { BdsTabPanel } from './bds-tab-panel';
|
|
|
26
26
|
*/
|
|
27
27
|
export class BdsTabs extends LitElement {
|
|
28
28
|
static styles = css`
|
|
29
|
+
/* Shadow DOM does not inherit the global box-sizing reset, so set it
|
|
30
|
+
here; otherwise elements with an explicit size + padding size as
|
|
31
|
+
content-box and layouts drift from the React (light-DOM) versions. */
|
|
32
|
+
:host,
|
|
33
|
+
*,
|
|
34
|
+
*::before,
|
|
35
|
+
*::after {
|
|
36
|
+
box-sizing: border-box;
|
|
37
|
+
}
|
|
38
|
+
|
|
29
39
|
:host {
|
|
30
40
|
display: flex;
|
|
31
41
|
flex-direction: column;
|
|
@@ -40,6 +50,7 @@ export class BdsTabs extends LitElement {
|
|
|
40
50
|
|
|
41
51
|
private _activeIndex = 0;
|
|
42
52
|
private _mo: MutationObserver | null = null;
|
|
53
|
+
private readonly _uid = Math.random().toString(36).slice(2, 8);
|
|
43
54
|
|
|
44
55
|
connectedCallback() {
|
|
45
56
|
super.connectedCallback();
|
|
@@ -70,7 +81,10 @@ export class BdsTabs extends LitElement {
|
|
|
70
81
|
private get _enabledIndexes(): number[] {
|
|
71
82
|
return this._tabs
|
|
72
83
|
.map((tab, i) => ({ tab, i }))
|
|
73
|
-
|
|
84
|
+
// Check the attribute too: on first render the reflected `disabled`
|
|
85
|
+
// property may not be set yet when _applyState runs, but the authored
|
|
86
|
+
// `disabled` attribute is already present.
|
|
87
|
+
.filter(({ tab }) => !tab.disabled && !tab.hasAttribute('disabled'))
|
|
74
88
|
.map(({ i }) => i);
|
|
75
89
|
}
|
|
76
90
|
|
|
@@ -83,8 +97,28 @@ export class BdsTabs extends LitElement {
|
|
|
83
97
|
this._activeIndex = Math.max(0, tabs.length - 1);
|
|
84
98
|
}
|
|
85
99
|
|
|
100
|
+
// A disabled tab must never be the active one. If the current active index
|
|
101
|
+
// is not an enabled tab (e.g. the default index-0 tab is <bds-tab disabled>),
|
|
102
|
+
// move selection to the first enabled tab — matching the React Tabs behaviour.
|
|
103
|
+
if (this._enabledIndexes.length && !this._enabledIndexes.includes(this._activeIndex)) {
|
|
104
|
+
this._activeIndex = this._enabledIndexes[0];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Assign role/id/aria-* on the light-DOM host elements (not the shadow-internal
|
|
108
|
+
// button/slot) — <bds-tab> and <bds-tab-panel> share the light-DOM tree with
|
|
109
|
+
// <bds-tabs>, so id-based aria-controls/aria-labelledby references resolve.
|
|
110
|
+
// Shadow-internal ids would not be valid IDREF targets from outside their root.
|
|
86
111
|
tabs.forEach((tab, i) => {
|
|
112
|
+
const panel = panels[i];
|
|
87
113
|
tab.selected = (i === this._activeIndex);
|
|
114
|
+
tab.setAttribute('role', 'tab');
|
|
115
|
+
if (!tab.id) tab.id = `bds-tabs-${this._uid}-tab-${i}`;
|
|
116
|
+
if (panel) {
|
|
117
|
+
if (!panel.id) panel.id = `bds-tabs-${this._uid}-panel-${i}`;
|
|
118
|
+
tab.setAttribute('aria-controls', panel.id);
|
|
119
|
+
panel.setAttribute('role', 'tabpanel');
|
|
120
|
+
panel.setAttribute('aria-labelledby', tab.id);
|
|
121
|
+
}
|
|
88
122
|
});
|
|
89
123
|
|
|
90
124
|
panels.forEach((panel, i) => {
|
|
@@ -106,6 +140,13 @@ export class BdsTabs extends LitElement {
|
|
|
106
140
|
};
|
|
107
141
|
|
|
108
142
|
private _handleKeydown = (e: KeyboardEvent) => {
|
|
143
|
+
// Only handle Arrow/Home/End when the key originates from a <bds-tab> (i.e. a
|
|
144
|
+
// tab button has focus). Without this guard the host-level listener hijacked
|
|
145
|
+
// these keys anywhere in the light DOM, including tab-panel content such as
|
|
146
|
+
// text inputs, sliders, or carousels.
|
|
147
|
+
const origin = e.target as Element | null;
|
|
148
|
+
if (!origin?.closest('bds-tab')) return;
|
|
149
|
+
|
|
109
150
|
const enabled = this._enabledIndexes;
|
|
110
151
|
if (!enabled.length) return;
|
|
111
152
|
|