@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
|
@@ -66,6 +66,69 @@ describe('bds-dropdown-menu', () => {
|
|
|
66
66
|
expect(el.open).toBe(false);
|
|
67
67
|
cleanup(el);
|
|
68
68
|
});
|
|
69
|
+
|
|
70
|
+
it('wires aria-haspopup, aria-controls and aria-expanded onto the slotted trigger', async () => {
|
|
71
|
+
const el = await fixture(`
|
|
72
|
+
<bds-dropdown-menu>
|
|
73
|
+
<button slot="trigger" type="button">Options</button>
|
|
74
|
+
<bds-dropdown-menu-item value="edit">Edit</bds-dropdown-menu-item>
|
|
75
|
+
</bds-dropdown-menu>
|
|
76
|
+
`) as BdsDropdownMenu;
|
|
77
|
+
await new Promise(r => requestAnimationFrame(() => r(null)));
|
|
78
|
+
const trigger = el.querySelector('button[slot="trigger"]')!;
|
|
79
|
+
const panel = el.shadowRoot!.querySelector('.panel')!;
|
|
80
|
+
|
|
81
|
+
expect(trigger.getAttribute('aria-haspopup')).toBe('menu');
|
|
82
|
+
expect(trigger.getAttribute('aria-controls')).toBe(panel.id);
|
|
83
|
+
expect(panel.id).not.toBe('');
|
|
84
|
+
expect(trigger.getAttribute('aria-expanded')).toBe('false');
|
|
85
|
+
|
|
86
|
+
cleanup(el);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('keeps aria-expanded on the trigger in sync with open/close', async () => {
|
|
90
|
+
const el = await fixture(`
|
|
91
|
+
<bds-dropdown-menu>
|
|
92
|
+
<button slot="trigger" type="button">Options</button>
|
|
93
|
+
<bds-dropdown-menu-item value="edit">Edit</bds-dropdown-menu-item>
|
|
94
|
+
</bds-dropdown-menu>
|
|
95
|
+
`) as BdsDropdownMenu;
|
|
96
|
+
await new Promise(r => requestAnimationFrame(() => r(null)));
|
|
97
|
+
const trigger = el.querySelector('button[slot="trigger"]')!;
|
|
98
|
+
|
|
99
|
+
el._open();
|
|
100
|
+
expect(trigger.getAttribute('aria-expanded')).toBe('true');
|
|
101
|
+
|
|
102
|
+
el._close();
|
|
103
|
+
expect(trigger.getAttribute('aria-expanded')).toBe('false');
|
|
104
|
+
|
|
105
|
+
cleanup(el);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('focuses the first item on Home and the last item on End', async () => {
|
|
109
|
+
const el = await fixture(`
|
|
110
|
+
<bds-dropdown-menu>
|
|
111
|
+
<button slot="trigger" type="button">Options</button>
|
|
112
|
+
<bds-dropdown-menu-item value="a">A</bds-dropdown-menu-item>
|
|
113
|
+
<bds-dropdown-menu-item value="b">B</bds-dropdown-menu-item>
|
|
114
|
+
<bds-dropdown-menu-item value="c">C</bds-dropdown-menu-item>
|
|
115
|
+
</bds-dropdown-menu>
|
|
116
|
+
`) as BdsDropdownMenu;
|
|
117
|
+
const items = [...el.querySelectorAll('bds-dropdown-menu-item')] as BdsDropdownMenuItem[];
|
|
118
|
+
el._open();
|
|
119
|
+
await Promise.all(items.map(item => item.updateComplete));
|
|
120
|
+
|
|
121
|
+
const buttons = items.map(item => item.shadowRoot!.querySelector<HTMLButtonElement>('button')!);
|
|
122
|
+
const focusSpies = buttons.map(btn => vi.spyOn(btn, 'focus'));
|
|
123
|
+
|
|
124
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: 'End', bubbles: true }));
|
|
125
|
+
expect(focusSpies[2]).toHaveBeenCalled();
|
|
126
|
+
|
|
127
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home', bubbles: true }));
|
|
128
|
+
expect(focusSpies[0]).toHaveBeenCalled();
|
|
129
|
+
|
|
130
|
+
cleanup(el);
|
|
131
|
+
});
|
|
69
132
|
});
|
|
70
133
|
|
|
71
134
|
describe('bds-dropdown-menu-item', () => {
|
|
@@ -6,9 +6,12 @@ export type DropdownMenuPlacement = 'bottom-start' | 'bottom-end' | 'top-start'
|
|
|
6
6
|
/**
|
|
7
7
|
* `<bds-dropdown-menu>` — anchored dropdown menu with keyboard navigation.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* The panel is an absolutely-positioned element inside the shadow root (not
|
|
10
|
+
* the native Popover API / top layer) — it can be clipped by an ancestor's
|
|
11
|
+
* `overflow` or stacking context. Light-dismiss is implemented via a
|
|
12
|
+
* document-level `click` listener. The trigger slot element controls
|
|
13
|
+
* open/close. The component handles keyboard navigation (Arrow keys, Home,
|
|
14
|
+
* End, Escape, Tab) and focus management.
|
|
12
15
|
*
|
|
13
16
|
* Attributes:
|
|
14
17
|
* open — controls open/closed state (reflected)
|
|
@@ -31,6 +34,16 @@ export type DropdownMenuPlacement = 'bottom-start' | 'bottom-end' | 'top-start'
|
|
|
31
34
|
*/
|
|
32
35
|
export class BdsDropdownMenu extends LitElement {
|
|
33
36
|
static styles = css`
|
|
37
|
+
/* Shadow DOM does not inherit the global box-sizing reset, so set it
|
|
38
|
+
here; otherwise elements with an explicit size + padding size as
|
|
39
|
+
content-box and layouts drift from the React (light-DOM) versions. */
|
|
40
|
+
:host,
|
|
41
|
+
*,
|
|
42
|
+
*::before,
|
|
43
|
+
*::after {
|
|
44
|
+
box-sizing: border-box;
|
|
45
|
+
}
|
|
46
|
+
|
|
34
47
|
:host {
|
|
35
48
|
display: inline-block;
|
|
36
49
|
position: relative;
|
|
@@ -41,11 +54,17 @@ export class BdsDropdownMenu extends LitElement {
|
|
|
41
54
|
inset-block-start: calc(100% + var(--bds-space_xxs));
|
|
42
55
|
inset-inline-start: 0;
|
|
43
56
|
min-inline-size: 10rem;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
57
|
+
border: var(--dropdown_border, none);
|
|
58
|
+
--bdc_color: currentcolor;
|
|
59
|
+
--bdc-outline_radius: var(--bds-border_radius--s);
|
|
60
|
+
|
|
61
|
+
border-radius: var(--dropdown_radius, var(--bdc-outline_radius));
|
|
62
|
+
background-color: var(--dropdown_color, var(--bds-color_bg));
|
|
63
|
+
color: var(--dropdown_on-color, var(--bds-color_on-bg));
|
|
64
|
+
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color),
|
|
65
|
+
var(--dropdown_shadow, var(--bds-shadow_m));
|
|
47
66
|
padding: var(--bds-space_xxs);
|
|
48
|
-
z-index: var(--bds-z-index_dropdown
|
|
67
|
+
z-index: var(--bds-z-index_dropdown);
|
|
49
68
|
display: none;
|
|
50
69
|
flex-direction: column;
|
|
51
70
|
}
|
|
@@ -81,6 +100,13 @@ export class BdsDropdownMenu extends LitElement {
|
|
|
81
100
|
declare open: boolean;
|
|
82
101
|
declare placement: DropdownMenuPlacement;
|
|
83
102
|
|
|
103
|
+
// Stable id for aria-controls wiring from the slotted trigger to the panel
|
|
104
|
+
private readonly _uid = Math.random().toString(36).slice(2, 8);
|
|
105
|
+
|
|
106
|
+
private get _panelId(): string {
|
|
107
|
+
return `bds-dropdown-panel-${this._uid}`;
|
|
108
|
+
}
|
|
109
|
+
|
|
84
110
|
constructor() {
|
|
85
111
|
super();
|
|
86
112
|
this.open = false;
|
|
@@ -115,6 +141,7 @@ export class BdsDropdownMenu extends LitElement {
|
|
|
115
141
|
_open() {
|
|
116
142
|
if (this.open) return;
|
|
117
143
|
this.open = true;
|
|
144
|
+
this._trigger?.setAttribute('aria-expanded', 'true');
|
|
118
145
|
this.dispatchEvent(new CustomEvent('bds-open', { bubbles: true, composed: true }));
|
|
119
146
|
// Focus first item after render
|
|
120
147
|
this.updateComplete.then(() => {
|
|
@@ -125,6 +152,7 @@ export class BdsDropdownMenu extends LitElement {
|
|
|
125
152
|
_close() {
|
|
126
153
|
if (!this.open) return;
|
|
127
154
|
this.open = false;
|
|
155
|
+
this._trigger?.setAttribute('aria-expanded', 'false');
|
|
128
156
|
this.dispatchEvent(new CustomEvent('bds-close', { bubbles: true, composed: true }));
|
|
129
157
|
this._trigger?.focus();
|
|
130
158
|
}
|
|
@@ -160,6 +188,12 @@ export class BdsDropdownMenu extends LitElement {
|
|
|
160
188
|
e.preventDefault();
|
|
161
189
|
const prev = (focused - 1 + items.length) % items.length;
|
|
162
190
|
items[prev]?.shadowRoot?.querySelector<HTMLElement>('button')?.focus();
|
|
191
|
+
} else if (e.key === 'Home') {
|
|
192
|
+
e.preventDefault();
|
|
193
|
+
items[0]?.shadowRoot?.querySelector<HTMLElement>('button')?.focus();
|
|
194
|
+
} else if (e.key === 'End') {
|
|
195
|
+
e.preventDefault();
|
|
196
|
+
items[items.length - 1]?.shadowRoot?.querySelector<HTMLElement>('button')?.focus();
|
|
163
197
|
} else if (e.key === 'Tab') {
|
|
164
198
|
this._close();
|
|
165
199
|
}
|
|
@@ -174,6 +208,9 @@ export class BdsDropdownMenu extends LitElement {
|
|
|
174
208
|
if (trigger) {
|
|
175
209
|
trigger.removeEventListener('click', this._handleTriggerClick);
|
|
176
210
|
trigger.addEventListener('click', this._handleTriggerClick);
|
|
211
|
+
trigger.setAttribute('aria-haspopup', 'menu');
|
|
212
|
+
trigger.setAttribute('aria-controls', this._panelId);
|
|
213
|
+
trigger.setAttribute('aria-expanded', String(this.open));
|
|
177
214
|
}
|
|
178
215
|
}
|
|
179
216
|
|
|
@@ -181,6 +218,7 @@ export class BdsDropdownMenu extends LitElement {
|
|
|
181
218
|
return html`
|
|
182
219
|
<slot name="trigger" @slotchange=${this._onTriggerSlotChange}></slot>
|
|
183
220
|
<div
|
|
221
|
+
id=${this._panelId}
|
|
184
222
|
class="panel"
|
|
185
223
|
role="menu"
|
|
186
224
|
aria-hidden=${!this.open ? 'true' : 'false'}
|
|
@@ -101,19 +101,93 @@ describe('bds-popover', () => {
|
|
|
101
101
|
|
|
102
102
|
it('injects a unique anchor-name CSS custom property on :host', async () => {
|
|
103
103
|
const el = await fixture('<bds-popover><button slot="trigger">Open</button></bds-popover>');
|
|
104
|
-
const anchorValue = el.style.getPropertyValue('--
|
|
105
|
-
expect(anchorValue).toMatch(/^--
|
|
104
|
+
const anchorValue = el.style.getPropertyValue('--popover-anchor');
|
|
105
|
+
expect(anchorValue).toMatch(/^--popover-[a-z0-9]+$/);
|
|
106
106
|
cleanup(el);
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
-
it('panel
|
|
109
|
+
it('panel omits role/aria-label by default (no aria-label attribute)', async () => {
|
|
110
110
|
const el = await fixture('<bds-popover><button slot="trigger">Open</button></bds-popover>');
|
|
111
111
|
const panel = el.shadowRoot!.querySelector('.panel');
|
|
112
|
+
expect(panel!.hasAttribute('role')).toBe(false);
|
|
113
|
+
expect(panel!.hasAttribute('aria-label')).toBe(false);
|
|
114
|
+
cleanup(el);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('forwards host aria-label to the panel and sets role="region"', async () => {
|
|
118
|
+
const el = await fixture(
|
|
119
|
+
'<bds-popover aria-label="Notifications"><button slot="trigger">Open</button></bds-popover>',
|
|
120
|
+
);
|
|
121
|
+
const panel = el.shadowRoot!.querySelector('.panel');
|
|
112
122
|
expect(panel!.getAttribute('role')).toBe('region');
|
|
113
|
-
expect(panel!.getAttribute('aria-label')).toBe('
|
|
123
|
+
expect(panel!.getAttribute('aria-label')).toBe('Notifications');
|
|
114
124
|
cleanup(el);
|
|
115
125
|
});
|
|
116
126
|
|
|
127
|
+
describe('trigger ARIA wiring', () => {
|
|
128
|
+
it('sets aria-haspopup and aria-controls on the slotted trigger', async () => {
|
|
129
|
+
const el = await fixture('<bds-popover><button slot="trigger">Open</button></bds-popover>');
|
|
130
|
+
await new Promise(r => requestAnimationFrame(() => r(null)));
|
|
131
|
+
const trigger = el.querySelector('button')!;
|
|
132
|
+
expect(trigger.getAttribute('aria-haspopup')).toBe('true');
|
|
133
|
+
expect(trigger.getAttribute('aria-controls')).toBeTruthy();
|
|
134
|
+
const panel = el.shadowRoot!.querySelector('.panel')!;
|
|
135
|
+
expect(trigger.getAttribute('aria-controls')).toBe(panel.id);
|
|
136
|
+
cleanup(el);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('sets aria-expanded="false" on the trigger by default', async () => {
|
|
140
|
+
const el = await fixture('<bds-popover><button slot="trigger">Open</button></bds-popover>');
|
|
141
|
+
await new Promise(r => requestAnimationFrame(() => r(null)));
|
|
142
|
+
const trigger = el.querySelector('button')!;
|
|
143
|
+
expect(trigger.getAttribute('aria-expanded')).toBe('false');
|
|
144
|
+
cleanup(el);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('flips the trigger aria-expanded to "true" when opened', async () => {
|
|
148
|
+
const el = await fixture('<bds-popover><button slot="trigger">Open</button></bds-popover>') as BdsPopover;
|
|
149
|
+
await new Promise(r => requestAnimationFrame(() => r(null)));
|
|
150
|
+
const trigger = el.querySelector('button')!;
|
|
151
|
+
el.shadowRoot!.querySelector('slot[name="trigger"]')!
|
|
152
|
+
.dispatchEvent(new MouseEvent('click', { bubbles: true, composed: true }));
|
|
153
|
+
await el.updateComplete;
|
|
154
|
+
expect(trigger.getAttribute('aria-expanded')).toBe('true');
|
|
155
|
+
cleanup(el);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
describe('focus restoration on close', () => {
|
|
160
|
+
it('restores focus to the trigger when Escape closes with focus inside the panel', async () => {
|
|
161
|
+
const el = await fixture(
|
|
162
|
+
'<bds-popover open><button slot="trigger">Open</button></bds-popover>',
|
|
163
|
+
) as BdsPopover;
|
|
164
|
+
await new Promise(r => requestAnimationFrame(() => r(null)));
|
|
165
|
+
const trigger = el.querySelector('button[slot="trigger"]') as HTMLElement;
|
|
166
|
+
// Focus is inside the popover (on the trigger itself) when Escape fires.
|
|
167
|
+
trigger.focus();
|
|
168
|
+
expect(document.activeElement).toBe(trigger);
|
|
169
|
+
const focusSpy = vi.spyOn(trigger, 'focus');
|
|
170
|
+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
|
|
171
|
+
await el.updateComplete;
|
|
172
|
+
expect(focusSpy).toHaveBeenCalled();
|
|
173
|
+
cleanup(el);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('does not steal focus when outside click closes the panel', async () => {
|
|
177
|
+
const outside = document.createElement('button');
|
|
178
|
+
document.body.appendChild(outside);
|
|
179
|
+
const el = await fixture('<bds-popover open><button slot="trigger">Open</button></bds-popover>') as BdsPopover;
|
|
180
|
+
await new Promise(r => requestAnimationFrame(() => r(null)));
|
|
181
|
+
outside.focus();
|
|
182
|
+
expect(document.activeElement).toBe(outside);
|
|
183
|
+
document.body.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
|
|
184
|
+
await el.updateComplete;
|
|
185
|
+
expect(document.activeElement).toBe(outside);
|
|
186
|
+
cleanup(el);
|
|
187
|
+
outside.remove();
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
117
191
|
describe('Invoker Commands API (command event on host)', () => {
|
|
118
192
|
it('opens on --open command', async () => {
|
|
119
193
|
const el = await fixture('<bds-popover id="p1"><button slot="trigger">T</button></bds-popover>') as BdsPopover;
|
|
@@ -165,8 +239,8 @@ describe('bds-popover', () => {
|
|
|
165
239
|
it('two instances get different anchor names', async () => {
|
|
166
240
|
const a = await fixture('<bds-popover><button slot="trigger">A</button></bds-popover>');
|
|
167
241
|
const b = await fixture('<bds-popover><button slot="trigger">B</button></bds-popover>');
|
|
168
|
-
const anchorA = a.style.getPropertyValue('--
|
|
169
|
-
const anchorB = b.style.getPropertyValue('--
|
|
242
|
+
const anchorA = a.style.getPropertyValue('--popover-anchor');
|
|
243
|
+
const anchorB = b.style.getPropertyValue('--popover-anchor');
|
|
170
244
|
expect(anchorA).not.toBe(anchorB);
|
|
171
245
|
cleanup(a);
|
|
172
246
|
cleanup(b);
|
|
@@ -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
|
});
|