@pnx-mixtape/mxds 0.1.0-rc.1 → 0.1.0-rc.3
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/.storybook/decorators.ts +15 -0
- package/.storybook/{preview.ts → preview.tsx} +8 -1
- package/.storybook/src/docs.tsx +29 -0
- package/.storybook/themes/campus-vibrant.css +181 -0
- package/.storybook/themes/civic-formal.css +246 -0
- package/.storybook/{theme-demo.css → themes/demo.css} +14 -7
- package/.storybook/themes/health-services.css +255 -0
- package/.storybook/themes/research-faculty.css +169 -0
- package/dist/build/accordion.css +1 -1
- package/dist/build/accordion.entry.js +1 -1
- package/dist/build/autocomplete.css +1 -1
- package/dist/build/autocomplete.entry.js +1 -1
- package/dist/build/base.css +1 -1
- package/dist/build/breadcrumb.css +1 -1
- package/dist/build/button.css +1 -1
- package/dist/build/card.css +1 -1
- package/dist/build/chunks/{Accordion-z-dH6nFH.js → Accordion-GN0sME4W.js} +1 -1
- package/dist/build/chunks/{AccordionMobile-BYPPNyf5.js → AccordionMobile-DG5jSe8Q.js} +1 -1
- package/dist/build/chunks/{Autocomplete-2L6tLLuh.js → Autocomplete-B4RtkAyh.js} +1 -1
- package/dist/build/chunks/{ClosableAlert-DdXbF1J2.js → ClosableAlert-DEhj8Nxm.js} +1 -1
- package/dist/build/chunks/{Dialog-Ds8gzhri.js → Dialog-Haahn-Yn.js} +1 -1
- package/dist/build/chunks/DropMenu-1baQc8Yc.js +1 -0
- package/dist/build/chunks/Gallery-D8NGXy2Q.js +1 -0
- package/dist/build/chunks/GlobalToggle-B52fdBQu.js +1 -0
- package/dist/build/chunks/InPageNavigation-Dyn2TR-N.js +1 -0
- package/dist/build/chunks/Navigation-hOrfLq7h.js +1 -0
- package/dist/build/chunks/Popover-Cxg-s5Jn.js +1 -0
- package/dist/build/chunks/Sticky-BGCuuEJK.js +1 -0
- package/dist/build/chunks/Tabs-DYy1YTdU.js +15 -0
- package/dist/build/chunks/enums-DLV_1NAf.js +1 -0
- package/dist/build/chunks/polyfills-C7pRt54M.js +1 -0
- package/dist/build/chunks/utilities-_Bq3TxAQ.js +1 -0
- package/dist/build/constants.css +1 -1
- package/dist/build/cookie-consent.css +1 -1
- package/dist/build/dialog.entry.js +1 -1
- package/dist/build/drop-menu.entry.js +1 -1
- package/dist/build/elements.js +1 -1
- package/dist/build/filters.css +1 -1
- package/dist/build/filters.entry.js +1 -1
- package/dist/build/form.css +1 -1
- package/dist/build/gallery.entry.js +1 -1
- package/dist/build/global-alert.entry.js +1 -1
- package/dist/build/grid.css +1 -1
- package/dist/build/header.entry.js +1 -1
- package/dist/build/icon.css +1 -1
- package/dist/build/in-page-alert.css +1 -1
- package/dist/build/in-page-navigation.entry.js +1 -1
- package/dist/build/list-item.css +1 -1
- package/dist/build/navigation.css +1 -1
- package/dist/build/navigation.entry.js +1 -1
- package/dist/build/one-time-code.css +1 -0
- package/dist/build/popover.css +1 -1
- package/dist/build/popover.entry.js +1 -1
- package/dist/build/print.css +1 -1
- package/dist/build/progress-indicator.css +1 -0
- package/dist/build/react.js +1 -1
- package/dist/build/sidebar.css +1 -1
- package/dist/build/steps.css +1 -1
- package/dist/build/sticky.entry.js +1 -1
- package/dist/build/tabs.css +1 -1
- package/dist/build/tabs.entry.js +1 -1
- package/dist/build/tag.css +1 -1
- package/dist/build/utilities.css +1 -1
- package/dist/types/Atom/DefinitionList/DefinitionList.d.ts +3 -2
- package/dist/types/Atom/DefinitionList/DefinitionList.d.ts.map +1 -1
- package/dist/types/Atom/Heading/Heading.d.ts.map +1 -1
- package/dist/types/Atom/Link/Link.d.ts.map +1 -1
- package/dist/types/Atom/List/List.d.ts +10 -0
- package/dist/types/Atom/List/List.d.ts.map +1 -0
- package/dist/types/Component/Accordion/Accordion.d.ts.map +1 -1
- package/dist/types/Component/Dialog/Dialog.d.ts.map +1 -1
- package/dist/types/Component/DropMenu/Elements/DropMenu.d.ts.map +1 -1
- package/dist/types/Component/Filters/Elements/Filters.d.ts +20 -1
- package/dist/types/Component/Filters/Elements/Filters.d.ts.map +1 -1
- package/dist/types/Component/Filters/Filters.d.ts +7 -2
- package/dist/types/Component/Filters/Filters.d.ts.map +1 -1
- package/dist/types/Component/Gallery/Gallery.d.ts.map +1 -1
- package/dist/types/Component/InPageNavigation/Elements/InPageNavigation.d.ts +2 -2
- package/dist/types/Component/InPageNavigation/Elements/InPageNavigation.d.ts.map +1 -1
- package/dist/types/Component/InPageNavigation/Hooks/useInPageNavigation.d.ts.map +1 -1
- package/dist/types/Component/Pagination/Components/PaginationContext.d.ts.map +1 -1
- package/dist/types/Component/ProgressIndicator/ProgressIndicator.d.ts +9 -0
- package/dist/types/Component/ProgressIndicator/ProgressIndicator.d.ts.map +1 -0
- package/dist/types/Component/Tabs/Elements/Tabs.d.ts.map +1 -1
- package/dist/types/Component/Tabs/Tabs.d.ts.map +1 -1
- package/dist/types/Component/Tag/Tag.d.ts +4 -2
- package/dist/types/Component/Tag/Tag.d.ts.map +1 -1
- package/dist/types/Form/Autocomplete/Autocomplete.d.ts +2 -2
- package/dist/types/Form/Autocomplete/Autocomplete.d.ts.map +1 -1
- package/dist/types/Form/Autocomplete/Elements/Autocomplete.d.ts +10 -0
- package/dist/types/Form/Autocomplete/Elements/Autocomplete.d.ts.map +1 -1
- package/dist/types/Form/Checkbox/FormCheckbox.d.ts.map +1 -1
- package/dist/types/Form/CheckboxCard/CheckboxCard.d.ts +23 -0
- package/dist/types/Form/CheckboxCard/CheckboxCard.d.ts.map +1 -0
- package/dist/types/Form/OneTimeCode/OneTimeCode.d.ts +12 -0
- package/dist/types/Form/OneTimeCode/OneTimeCode.d.ts.map +1 -0
- package/dist/types/Form/Radio/FormRadio.d.ts.map +1 -1
- package/dist/types/Form/RadioCard/RadioCard.d.ts +16 -0
- package/dist/types/Form/RadioCard/RadioCard.d.ts.map +1 -0
- package/dist/types/Form/Select/FormSelect.d.ts.map +1 -1
- package/dist/types/Form/TextInput/FormText.d.ts.map +1 -1
- package/dist/types/Form/Textarea/FormTextarea.d.ts.map +1 -1
- package/dist/types/Utility/Hooks/useIsomorphicLayoutEffect.d.ts +4 -0
- package/dist/types/Utility/Hooks/useIsomorphicLayoutEffect.d.ts.map +1 -0
- package/dist/types/enums.d.ts +19 -0
- package/dist/types/enums.d.ts.map +1 -1
- package/dist/types/react.d.ts +5 -0
- package/dist/types/react.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/Atom/Background/_background.css +2 -2
- package/src/Atom/Blockquote/_blockquote.css +9 -2
- package/src/Atom/Button/README.md +1 -0
- package/src/Atom/Button/__snapshots__/Button.stories.ts.snap +2 -3
- package/src/Atom/Button/_buttons-styles.css +6 -6
- package/src/Atom/Button/_buttons.css +21 -3
- package/src/Atom/Button/button.twig +4 -1
- package/src/Atom/DefinitionList/DefinitionList.stories.ts +42 -2
- package/src/Atom/DefinitionList/DefinitionList.stories.tsx +36 -0
- package/src/Atom/DefinitionList/DefinitionList.tsx +4 -1
- package/src/Atom/DefinitionList/DefinitionListItem.stories.ts +1 -1
- package/src/Atom/DefinitionList/README.md +43 -0
- package/src/Atom/DefinitionList/__snapshots__/DefinitionList.stories.ts.snap +37 -3
- package/src/Atom/DefinitionList/__snapshots__/DefinitionList.stories.tsx.snap +2 -0
- package/src/Atom/DefinitionList/__snapshots__/DefinitionListItem.stories.ts.snap +3 -3
- package/src/Atom/DefinitionList/definition-list-item.twig +1 -0
- package/src/Atom/DefinitionList/definition-list.twig +6 -1
- package/src/Atom/Heading/Heading.tsx +6 -0
- package/src/Atom/Heading/_headings.css +2 -1
- package/src/Atom/Icon/_extended-set.css +30 -30
- package/src/Atom/Icon/_icon.css +39 -36
- package/src/Atom/Image/README.md +2 -2
- package/src/Atom/Image/_image.css +12 -6
- package/src/Atom/Link/Link.tsx +16 -3
- package/src/Atom/Link/__snapshots__/Link.stories.ts.snap +7 -12
- package/src/Atom/Link/__snapshots__/Link.stories.tsx.snap +1 -1
- package/src/Atom/Link/_links.css +9 -0
- package/src/Atom/Link/link.twig +8 -2
- package/src/Atom/LinkedImage/linked-image.twig +1 -2
- package/src/Atom/List/List.stories.ts +102 -0
- package/src/Atom/List/List.stories.tsx +103 -0
- package/src/Atom/List/List.tsx +22 -0
- package/src/Atom/List/README.md +150 -0
- package/src/Atom/List/__snapshots__/List.stories.ts.snap +43 -0
- package/src/Atom/List/__snapshots__/List.stories.tsx.snap +13 -0
- package/src/Atom/List/_list.css +123 -0
- package/src/Atom/List/list.twig +5 -0
- package/src/Atom/Media/Media.stories.ts +1 -1
- package/src/Atom/Media/__snapshots__/Media.stories.ts.snap +2 -2
- package/src/Atom/Spacing/_spacing.css +24 -24
- package/src/Atom/Table/__snapshots__/Table.stories.ts.snap +24 -4
- package/src/Atom/Table/_table.css +15 -3
- package/src/Atom/Table/table.twig +6 -1
- package/src/Atom/Text/__snapshots__/Text.stories.ts.snap +3 -2
- package/src/Atom/Text/_text-styles.css +21 -1
- package/src/Atom/Text/twig/text-styles-example.twig +3 -2
- package/src/Atom/_base.css +6 -0
- package/src/Atom/_flow.css +1 -1
- package/src/Atom/_generic.css +18 -11
- package/src/Component/Accordion/Accordion.stories.ts +31 -0
- package/src/Component/Accordion/Accordion.tsx +3 -2
- package/src/Component/Accordion/AccordionItem.stories.ts +27 -0
- package/src/Component/Accordion/__snapshots__/Accordion.stories.ts.snap +36 -0
- package/src/Component/Accordion/__snapshots__/AccordionItem.stories.ts.snap +16 -0
- package/src/Component/Accordion/accordion.css +2 -0
- package/src/Component/Breadcrumb/__snapshots__/Breadcrumb.stories.ts.snap +3 -6
- package/src/Component/Breadcrumb/breadcrumb.css +4 -0
- package/src/Component/Card/__snapshots__/Card.stories.ts.snap +13 -24
- package/src/Component/Card/card.css +2 -2
- package/src/Component/Card/card.twig +1 -1
- package/src/Component/Carousel/Carousel.stories.ts +101 -23
- package/src/Component/Carousel/Carousel.stories.tsx +74 -0
- package/src/Component/Carousel/__snapshots__/Carousel.stories.ts.snap +273 -88
- package/src/Component/Carousel/__snapshots__/Carousel.stories.tsx.snap +5 -3
- package/src/Component/ContentBlock/__snapshots__/ContentBlock.stories.ts.snap +12 -24
- package/src/Component/CookieConsent/cookie-consent.css +3 -1
- package/src/Component/Dialog/Dialog.stories.ts +33 -0
- package/src/Component/Dialog/Dialog.stories.tsx +25 -0
- package/src/Component/Dialog/Dialog.tsx +2 -2
- package/src/Component/Dialog/__snapshots__/Dialog.stories.ts.snap +33 -2
- package/src/Component/Dialog/__snapshots__/Dialog.stories.tsx.snap +2 -0
- package/src/Component/DropMenu/DropMenu.stories.ts +39 -1
- package/src/Component/DropMenu/DropMenu.stories.tsx +29 -0
- package/src/Component/DropMenu/DropMenu.tsx +1 -1
- package/src/Component/DropMenu/Elements/DropMenu.ts +10 -1
- package/src/Component/DropMenu/__snapshots__/DropMenu.stories.ts.snap +14 -0
- package/src/Component/DropMenu/__snapshots__/DropMenu.stories.tsx.snap +3 -1
- package/src/Component/Filters/Elements/Filters.ts +71 -1
- package/src/Component/Filters/FilterItem.stories.ts +2 -1
- package/src/Component/Filters/FilterItem.tsx +1 -1
- package/src/Component/Filters/Filters.figma.ts +1 -1
- package/src/Component/Filters/Filters.stories.ts +95 -3
- package/src/Component/Filters/Filters.stories.tsx +246 -17
- package/src/Component/Filters/Filters.tsx +145 -29
- package/src/Component/Filters/README.md +102 -37
- package/src/Component/Filters/__snapshots__/FilterItem.stories.tsx.snap +3 -3
- package/src/Component/Filters/__snapshots__/Filters.stories.ts.snap +82 -4
- package/src/Component/Filters/__snapshots__/Filters.stories.tsx.snap +9 -3
- package/src/Component/Filters/filters.css +11 -0
- package/src/Component/Gallery/Gallery.tsx +2 -2
- package/src/Component/HeroBanner/HeroBanner.stories.ts +1 -1
- package/src/Component/HeroBanner/__snapshots__/HeroBanner.stories.ts.snap +4 -8
- package/src/Component/HeroSearch/__snapshots__/HeroSearch.stories.ts.snap +5 -10
- package/src/Component/InPageAlert/__snapshots__/InPageAlert.stories.ts.snap +6 -12
- package/src/Component/InPageAlert/in-page-alert.css +2 -1
- package/src/Component/InPageNavigation/Elements/InPageNavigation.ts +10 -5
- package/src/Component/InPageNavigation/Hooks/useInPageNavigation.ts +10 -5
- package/src/Component/InPageNavigation/InPageNavigation.stories.ts +83 -0
- package/src/Component/InPageNavigation/InPageNavigation.stories.tsx +130 -0
- package/src/Component/InPageNavigation/__snapshots__/InPageNavigation.stories.ts.snap +61 -1
- package/src/Component/InPageNavigation/__snapshots__/InPageNavigation.stories.tsx.snap +4 -0
- package/src/Component/InPageNavigation/twig/content-example-duplicate-headings.twig +20 -0
- package/src/Component/InPageNavigation/twig/in-page-navigation-story-duplicate-headings.twig +2 -0
- package/src/Component/LinkList/__snapshots__/LinkList.stories.ts.snap +6 -12
- package/src/Component/ListItem/__snapshots__/ListItem.stories.ts.snap +11 -18
- package/src/Component/ListItem/list-item.css +1 -1
- package/src/Component/ListItem/list-item.twig +2 -2
- package/src/Component/Navigation/Dropdown.stories.tsx +46 -0
- package/src/Component/Navigation/Navigation.stories.ts +56 -0
- package/src/Component/Navigation/__snapshots__/Dropdown.stories.tsx.snap +2 -0
- package/src/Component/Navigation/__snapshots__/Navigation.stories.ts.snap +57 -0
- package/src/Component/Navigation/_navigation.css +1 -1
- package/src/Component/Pagination/Components/PaginationContext.tsx +2 -1
- package/src/Component/Pagination/Components/PaginationItem.tsx +1 -1
- package/src/Component/Pagination/Pagination.stories.ts +44 -4
- package/src/Component/Pagination/Pagination.stories.tsx +31 -0
- package/src/Component/Pagination/__snapshots__/Pagination.stories.ts.snap +69 -12
- package/src/Component/Pagination/__snapshots__/Pagination.stories.tsx.snap +3 -1
- package/src/Component/Pagination/pagination-item.twig +1 -1
- package/src/Component/Pagination/pagination.css +2 -2
- package/src/Component/Popover/__snapshots__/Popover.stories.ts.snap +13 -26
- package/src/Component/Popover/popover.css +1 -1
- package/src/Component/ProgressIndicator/ProgressIndicator.stories.ts +36 -0
- package/src/Component/ProgressIndicator/ProgressIndicator.stories.tsx +30 -0
- package/src/Component/ProgressIndicator/ProgressIndicator.tsx +60 -0
- package/src/Component/ProgressIndicator/README.md +111 -0
- package/src/Component/ProgressIndicator/__snapshots__/ProgressIndicator.stories.ts.snap +67 -0
- package/src/Component/ProgressIndicator/__snapshots__/ProgressIndicator.stories.tsx.snap +7 -0
- package/src/Component/ProgressIndicator/progress-indicator.css +59 -0
- package/src/Component/ProgressIndicator/progress-indicator.twig +22 -0
- package/src/Component/SideNavigation/__snapshots__/SideNavigation.stories.ts.snap +1 -2
- package/src/Component/SocialLinks/__snapshots__/SocialLinks.stories.ts.snap +6 -9
- package/src/Component/Steps/Steps.stories.ts +1 -1
- package/src/Component/Steps/steps.css +13 -0
- package/src/Component/Sticky/Elements/Sticky.ts +1 -1
- package/src/Component/Sticky/sticky.css +3 -3
- package/src/Component/Tabs/Elements/Tabs.ts +3 -1
- package/src/Component/Tabs/Tabs.stories.ts +77 -21
- package/src/Component/Tabs/Tabs.stories.tsx +24 -0
- package/src/Component/Tabs/Tabs.tsx +2 -2
- package/src/Component/Tabs/__snapshots__/Tabs.stories.ts.snap +20 -2
- package/src/Component/Tabs/__snapshots__/Tabs.stories.tsx.snap +3 -1
- package/src/Component/Tabs/tabs.css +2 -0
- package/src/Component/Tag/README.md +52 -26
- package/src/Component/Tag/Tag.stories.tsx +24 -0
- package/src/Component/Tag/Tag.tsx +12 -2
- package/src/Component/Tag/TagItem.stories.ts +25 -0
- package/src/Component/Tag/__snapshots__/Tag.stories.ts.snap +2 -2
- package/src/Component/Tag/__snapshots__/Tag.stories.tsx.snap +2 -0
- package/src/Component/Tag/tag-item.twig +2 -2
- package/src/Component/Tag/tag.css +76 -2
- package/src/Form/Autocomplete/Autocomplete.stories.ts +89 -7
- package/src/Form/Autocomplete/Autocomplete.stories.tsx +85 -1
- package/src/Form/Autocomplete/Autocomplete.tsx +20 -10
- package/src/Form/Autocomplete/Elements/Autocomplete.ts +24 -1
- package/src/Form/Autocomplete/README.md +26 -26
- package/src/Form/Autocomplete/__snapshots__/Autocomplete.stories.ts.snap +39 -5
- package/src/Form/Autocomplete/__snapshots__/Autocomplete.stories.tsx.snap +8 -4
- package/src/Form/Autocomplete/autocomplete.css +12 -1
- package/src/Form/Autocomplete/autocomplete.twig +1 -3
- package/src/Form/Checkbox/FormCheckbox.tsx +2 -8
- package/src/Form/Checkbox/README.md +23 -18
- package/src/Form/Checkbox/input-checkbox.twig +0 -2
- package/src/Form/CheckboxCard/CheckboxCard.stories.ts +90 -0
- package/src/Form/CheckboxCard/CheckboxCard.stories.tsx +43 -0
- package/src/Form/CheckboxCard/CheckboxCard.tsx +102 -0
- package/src/Form/CheckboxCard/README.md +163 -0
- package/src/Form/CheckboxCard/__snapshots__/CheckboxCard.stories.ts.snap +63 -0
- package/src/Form/CheckboxCard/__snapshots__/CheckboxCard.stories.tsx.snap +7 -0
- package/src/Form/CheckboxCard/checkbox-card.twig +29 -0
- package/src/Form/FormItem/__snapshots__/FormItem.stories.ts.snap +2 -2
- package/src/Form/OneTimeCode/OneTimeCode.stories.ts +20 -0
- package/src/Form/OneTimeCode/OneTimeCode.stories.tsx +18 -0
- package/src/Form/OneTimeCode/OneTimeCode.tsx +56 -0
- package/src/Form/OneTimeCode/README.md +83 -0
- package/src/Form/OneTimeCode/__snapshots__/OneTimeCode.stories.ts.snap +7 -0
- package/src/Form/OneTimeCode/__snapshots__/OneTimeCode.stories.tsx.snap +3 -0
- package/src/Form/OneTimeCode/one-time-code.css +13 -0
- package/src/Form/OneTimeCode/one-time-code.twig +31 -0
- package/src/Form/README.md +65 -13
- package/src/Form/Radio/FormRadio.tsx +1 -4
- package/src/Form/Radio/input-radio.twig +0 -2
- package/src/Form/RadioCard/README.md +146 -0
- package/src/Form/RadioCard/RadioCard.stories.ts +95 -0
- package/src/Form/RadioCard/RadioCard.stories.tsx +26 -0
- package/src/Form/RadioCard/RadioCard.tsx +59 -0
- package/src/Form/RadioCard/__snapshots__/RadioCard.stories.ts.snap +69 -0
- package/src/Form/RadioCard/__snapshots__/RadioCard.stories.tsx.snap +3 -0
- package/src/Form/RadioCard/radio-card.twig +20 -0
- package/src/Form/Select/FormSelect.tsx +1 -4
- package/src/Form/Select/input-select.twig +0 -2
- package/src/Form/TextInput/FormText.stories.tsx +14 -0
- package/src/Form/TextInput/FormText.tsx +1 -4
- package/src/Form/TextInput/__snapshots__/FormText.stories.tsx.snap +2 -0
- package/src/Form/TextInput/input-text.twig +0 -2
- package/src/Form/Textarea/FormTextarea.tsx +1 -4
- package/src/Form/Textarea/input-textarea.twig +0 -2
- package/src/Form/Validation.stories.ts +153 -0
- package/src/Form/__snapshots__/Validation.stories.ts.snap +130 -0
- package/src/Form/form.css +240 -55
- package/src/Layout/Footer/__snapshots__/Footer.stories.ts.snap +18 -33
- package/src/Layout/Grid/grid.css +4 -4
- package/src/Layout/Header/Header.stories.ts +33 -0
- package/src/Layout/Header/Header.stories.tsx +31 -0
- package/src/Layout/Header/__snapshots__/Header.stories.ts.snap +50 -0
- package/src/Layout/Header/__snapshots__/Header.stories.tsx.snap +2 -0
- package/src/Layout/Masthead/__snapshots__/Masthead.stories.ts.snap +8 -16
- package/src/Layout/Section/__snapshots__/Background.stories.ts.snap +2 -4
- package/src/Layout/Section/__snapshots__/Section.stories.ts.snap +4 -8
- package/src/Layout/Sidebar/__snapshots__/Sidebar.stories.ts.snap +5 -5
- package/src/Layout/Sidebar/sidebar.css +1 -0
- package/src/Layout/Sidebar/sidebar.twig +1 -1
- package/src/Utility/Hooks/useIsomorphicLayoutEffect.ts +8 -0
- package/src/Utility/_layout-utils.css +8 -0
- package/src/Utility/_mixins.css +24 -0
- package/src/Utility/print.css +51 -29
- package/src/Utility/utilities.css +22 -2
- package/src/_custom-media.css +1 -0
- package/src/constants.css +12 -2
- package/src/enums.ts +22 -0
- package/src/react.ts +5 -0
- package/tools/lib/extract-classnames.mjs +0 -0
- package/tools/lint-classnames.mjs +1 -1
- package/tools/test-utils/screen-reader.ts +33 -0
- package/dist/build/chunks/DropMenu-Co9jZZ4S.js +0 -1
- package/dist/build/chunks/Gallery-BT3cxS5m.js +0 -1
- package/dist/build/chunks/GlobalToggle-DQHho97V.js +0 -1
- package/dist/build/chunks/InPageNavigation-CzR_KZaz.js +0 -1
- package/dist/build/chunks/Navigation-B9Wug-ok.js +0 -1
- package/dist/build/chunks/Popover-De_CQqcd.js +0 -1
- package/dist/build/chunks/Sticky-Kyjykb36.js +0 -1
- package/dist/build/chunks/Tabs-Dm8g301e.js +0 -15
- package/dist/build/chunks/disclosure-widget-BETzOHLO.js +0 -1
- package/dist/build/chunks/polyfills-Dokbkxxk.js +0 -1
- package/dist/build/chunks/utilities-C5dAO2YA.js +0 -1
|
@@ -4,12 +4,13 @@ import {
|
|
|
4
4
|
ChangeEventHandler,
|
|
5
5
|
KeyboardEventHandler,
|
|
6
6
|
MouseEventHandler,
|
|
7
|
-
useEffect,
|
|
8
7
|
useRef,
|
|
8
|
+
useState,
|
|
9
9
|
ReactNode,
|
|
10
10
|
} from "react"
|
|
11
11
|
import classNames from "classnames"
|
|
12
12
|
import { useComboBoxState, Item } from "react-stately"
|
|
13
|
+
import useIsomorphicLayoutEffect from "../../Utility/Hooks/useIsomorphicLayoutEffect"
|
|
13
14
|
import { FormStatus } from "../../enums"
|
|
14
15
|
|
|
15
16
|
export type AutocompleteOption = {
|
|
@@ -33,8 +34,8 @@ export type AutocompleteProps = Omit<ComponentPropsWithoutRef<"input">, "value"
|
|
|
33
34
|
className?: string
|
|
34
35
|
noResultsLabel?: string
|
|
35
36
|
hideOnBlur?: boolean
|
|
36
|
-
/** Called on every keystroke with the trimmed input value — do the actual search here (debounce it yourself) and feed the results back in via `options`. */
|
|
37
|
-
onSearch?: (query: string) => void
|
|
37
|
+
/** Called on every keystroke with the trimmed input value — do the actual search here (debounce it yourself) and feed the results back in via `options`. Return a promise to drive the built-in pending state (`aria-busy` on the control, which also shows a spinner) while it resolves. */
|
|
38
|
+
onSearch?: (query: string) => void | Promise<void>
|
|
38
39
|
onSelect?: (option: AutocompleteOption) => void
|
|
39
40
|
onSubmit?: MouseEventHandler<HTMLButtonElement>
|
|
40
41
|
children?: ReactNode
|
|
@@ -65,6 +66,11 @@ const Autocomplete = ({
|
|
|
65
66
|
}: AutocompleteProps): JSX.Element => {
|
|
66
67
|
const inputRef = useRef<HTMLInputElement>(null)
|
|
67
68
|
const listboxRef = useRef<HTMLUListElement>(null)
|
|
69
|
+
// Tracks which `onSearch` call is the most recent, so an out-of-order
|
|
70
|
+
// (slower) earlier response can't clear pending after a newer search has
|
|
71
|
+
// already started.
|
|
72
|
+
const searchTokenRef = useRef<number>(0)
|
|
73
|
+
const [pending, setPending] = useState<boolean>(false)
|
|
68
74
|
|
|
69
75
|
// `useComboBoxState` gives us the collection (for Home/End/next/prev key
|
|
70
76
|
// lookups), focused-key tracking, and input-value tracking, replacing
|
|
@@ -106,7 +112,7 @@ const Autocomplete = ({
|
|
|
106
112
|
const listboxId = `${id}-listbox`
|
|
107
113
|
const activeId = activeIndex >= 0 ? `${id}-option-${activeIndex}` : undefined
|
|
108
114
|
|
|
109
|
-
|
|
115
|
+
useIsomorphicLayoutEffect(() => {
|
|
110
116
|
listboxRef.current
|
|
111
117
|
?.querySelector('[aria-selected="true"]')
|
|
112
118
|
?.scrollIntoView({ block: "nearest" })
|
|
@@ -126,7 +132,14 @@ const Autocomplete = ({
|
|
|
126
132
|
state.selectionManager.setFocusedKey(null)
|
|
127
133
|
if (currentTarget.value.trim().length > 0) state.open()
|
|
128
134
|
else closeMenu()
|
|
129
|
-
onSearch?.(currentTarget.value.trim())
|
|
135
|
+
const result = onSearch?.(currentTarget.value.trim())
|
|
136
|
+
if (result) {
|
|
137
|
+
const token = ++searchTokenRef.current
|
|
138
|
+
setPending(true)
|
|
139
|
+
result.finally(() => {
|
|
140
|
+
if (searchTokenRef.current === token) setPending(false)
|
|
141
|
+
})
|
|
142
|
+
}
|
|
130
143
|
}
|
|
131
144
|
|
|
132
145
|
const handleFocus = (): void => {
|
|
@@ -200,17 +213,14 @@ const Autocomplete = ({
|
|
|
200
213
|
|
|
201
214
|
return (
|
|
202
215
|
<div className={classNames("mx-autocomplete", className)}>
|
|
203
|
-
<div className="mx-autocomplete__control mx-form--inline-button">
|
|
216
|
+
<div className="mx-autocomplete__control mx-form--inline-button" aria-busy={pending}>
|
|
204
217
|
<input
|
|
205
218
|
{...props}
|
|
206
219
|
ref={inputRef}
|
|
207
220
|
id={id}
|
|
208
221
|
type={type}
|
|
209
222
|
role="combobox"
|
|
210
|
-
className=
|
|
211
|
-
error: status === FormStatus.INVALID,
|
|
212
|
-
success: status === FormStatus.VALID,
|
|
213
|
-
})}
|
|
223
|
+
className="mx-input__text"
|
|
214
224
|
value={state.inputValue}
|
|
215
225
|
autoComplete="off"
|
|
216
226
|
aria-expanded={state.isOpen}
|
|
@@ -8,6 +8,13 @@
|
|
|
8
8
|
* Elasticsearch call). A MutationObserver watches the listbox for those DOM
|
|
9
9
|
* changes and updates aria-expanded/aria-activedescendant/the status message
|
|
10
10
|
* to match whatever options currently exist.
|
|
11
|
+
*
|
|
12
|
+
* The `pending` property is fully consumer-controlled — there's no promise to
|
|
13
|
+
* await here, only an event — so set `el.pending = true` before your search
|
|
14
|
+
* call and `= false` once it settles. It reflects `aria-busy` on the control,
|
|
15
|
+
* the same contract the React implementation exposes: one attribute drives
|
|
16
|
+
* both the assistive-tech signal and the spinner (see the generic
|
|
17
|
+
* `[aria-busy="true"]` utility in Utility/utilities.css).
|
|
11
18
|
*/
|
|
12
19
|
|
|
13
20
|
export type AutocompleteSearchEvent = CustomEvent<{ query: string }>
|
|
@@ -191,8 +198,16 @@ export default class Autocomplete extends HTMLElement {
|
|
|
191
198
|
return this.dataset.noResultsLabel || "No results found"
|
|
192
199
|
}
|
|
193
200
|
|
|
201
|
+
get control(): HTMLDivElement {
|
|
202
|
+
const div = this.querySelector<HTMLDivElement>("[data-control]")
|
|
203
|
+
if (!div) {
|
|
204
|
+
throw new Error(`${this.localName} must contain a [data-control] element.`)
|
|
205
|
+
}
|
|
206
|
+
return div
|
|
207
|
+
}
|
|
208
|
+
|
|
194
209
|
get input(): HTMLInputElement {
|
|
195
|
-
const input = this.querySelector<HTMLInputElement>('input[role="combobox"]')
|
|
210
|
+
const input = this.control.querySelector<HTMLInputElement>('input[role="combobox"]')
|
|
196
211
|
if (!input) {
|
|
197
212
|
throw new Error(`${this.localName} must contain an <input role="combobox">.`)
|
|
198
213
|
}
|
|
@@ -222,6 +237,14 @@ export default class Autocomplete extends HTMLElement {
|
|
|
222
237
|
get visibleOptions(): HTMLLIElement[] {
|
|
223
238
|
return this.options.filter(option => !option.hidden)
|
|
224
239
|
}
|
|
240
|
+
|
|
241
|
+
get pending(): boolean {
|
|
242
|
+
return this.control.getAttribute("aria-busy") === "true"
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
set pending(value: boolean) {
|
|
246
|
+
this.control.setAttribute("aria-busy", String(value))
|
|
247
|
+
}
|
|
225
248
|
}
|
|
226
249
|
|
|
227
250
|
if (!customElements.get("mx-autocomplete")) {
|
|
@@ -32,18 +32,18 @@ This is a field-level component only — pair it with `FormItem` and `FormLabel`
|
|
|
32
32
|
|
|
33
33
|
**autocomplete.twig props:**
|
|
34
34
|
|
|
35
|
-
| Prop | Type | Required | Default | Description
|
|
36
|
-
| ---------------- | ------------------------------------ | -------- | -------------------- |
|
|
37
|
-
| `id` | `string` | Yes | — | `id` on the `<input>`; also used to derive the listbox/option ids
|
|
38
|
-
| `name` | `string` | No | — | `name` attribute on the `<input>`
|
|
39
|
-
| `label` | `string` | No | — | `aria-label` on the `<input>` (visually hidden)
|
|
40
|
-
| `type` | `"text" \| "search"` | No | `"text"` | `"search"` also renders an icon-only submit button
|
|
41
|
-
| `options` | `{ label: string, value: string }[]` | No | — | The **current** suggestions to render as `<li role="option">` — not a full list to filter, see below
|
|
42
|
-
| `value` | `string` | No | — | Initial `<input>` value
|
|
43
|
-
| `placeholder` | `string` | No | — | `<input>` placeholder
|
|
44
|
-
| `required` | `boolean` | No | `false` | Adds `required` to the `<input>`
|
|
45
|
-
| `status` | `"default" \| "valid" \| "invalid"` | No | `"default"` |
|
|
46
|
-
| `noResultsLabel` | `string` | No | `"No results found"` | Message announced when there are zero current options and a query
|
|
35
|
+
| Prop | Type | Required | Default | Description |
|
|
36
|
+
| ---------------- | ------------------------------------ | -------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
37
|
+
| `id` | `string` | Yes | — | `id` on the `<input>`; also used to derive the listbox/option ids |
|
|
38
|
+
| `name` | `string` | No | — | `name` attribute on the `<input>` |
|
|
39
|
+
| `label` | `string` | No | — | `aria-label` on the `<input>` (visually hidden) |
|
|
40
|
+
| `type` | `"text" \| "search"` | No | `"text"` | `"search"` also renders an icon-only submit button |
|
|
41
|
+
| `options` | `{ label: string, value: string }[]` | No | — | The **current** suggestions to render as `<li role="option">` — not a full list to filter, see below |
|
|
42
|
+
| `value` | `string` | No | — | Initial `<input>` value |
|
|
43
|
+
| `placeholder` | `string` | No | — | `<input>` placeholder |
|
|
44
|
+
| `required` | `boolean` | No | `false` | Adds `required` to the `<input>` |
|
|
45
|
+
| `status` | `"default" \| "valid" \| "invalid"` | No | `"default"` | Sets `aria-invalid` on the `<input>` (red border). Live `:user-*` colours need `mx-validate` on the `<input>` or the `.mx-autocomplete` wrapper |
|
|
46
|
+
| `noResultsLabel` | `string` | No | `"No results found"` | Message announced when there are zero current options and a query |
|
|
47
47
|
|
|
48
48
|
Registers as `<mx-autocomplete>` — import the element to activate its behaviour:
|
|
49
49
|
|
|
@@ -140,19 +140,19 @@ const Example = () => {
|
|
|
140
140
|
|
|
141
141
|
**`Autocomplete` props:**
|
|
142
142
|
|
|
143
|
-
| Prop | Type | Default | Description
|
|
144
|
-
| ---------------- | -------------------------------------- | -------------------- |
|
|
145
|
-
| `id` | `string` | — | `id` on the `<input>`; also used to derive the listbox/option ids
|
|
146
|
-
| `label` | `string` | — | `aria-label` on the `<input>` (visually hidden)
|
|
147
|
-
| `type` | `"text" \| "search"` | `"text"` | `"search"` also renders an icon-only submit button (`onSubmit`)
|
|
148
|
-
| `options` | `AutocompleteOption[]` | — | The **current** results to display — not filtered further, see below
|
|
149
|
-
| `onSearch` | `(query: string) => void` | — | Called on every keystroke with the trimmed input value — debounce it yourself and feed matches back in via `options`
|
|
150
|
-
| `value` | `string` | `""` | Initial `<input>` value (uncontrolled after that)
|
|
151
|
-
| `status` | `FormStatus` | `FormStatus.DEFAULT` |
|
|
152
|
-
| `noResultsLabel` | `string` | `"No results found"` | Message announced when `options` is empty and there's a query
|
|
153
|
-
| `onSelect` | `(option: AutocompleteOption) => void` | — | Called when an option is chosen by click or <kbd>Enter</kbd>
|
|
154
|
-
| `hideOnBlur` | `boolean` | `true` | Close the listbox on blur
|
|
155
|
-
| `className` | `string` | — | Extra class on the root
|
|
143
|
+
| Prop | Type | Default | Description |
|
|
144
|
+
| ---------------- | -------------------------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
145
|
+
| `id` | `string` | — | `id` on the `<input>`; also used to derive the listbox/option ids |
|
|
146
|
+
| `label` | `string` | — | `aria-label` on the `<input>` (visually hidden) |
|
|
147
|
+
| `type` | `"text" \| "search"` | `"text"` | `"search"` also renders an icon-only submit button (`onSubmit`) |
|
|
148
|
+
| `options` | `AutocompleteOption[]` | — | The **current** results to display — not filtered further, see below |
|
|
149
|
+
| `onSearch` | `(query: string) => void` | — | Called on every keystroke with the trimmed input value — debounce it yourself and feed matches back in via `options` |
|
|
150
|
+
| `value` | `string` | `""` | Initial `<input>` value (uncontrolled after that) |
|
|
151
|
+
| `status` | `FormStatus` | `FormStatus.DEFAULT` | Sets `aria-invalid` (red border). Live `:user-*` colours need `mx-validate` on the `.mx-autocomplete` wrapper — `className` lands there, not on the input |
|
|
152
|
+
| `noResultsLabel` | `string` | `"No results found"` | Message announced when `options` is empty and there's a query |
|
|
153
|
+
| `onSelect` | `(option: AutocompleteOption) => void` | — | Called when an option is chosen by click or <kbd>Enter</kbd> |
|
|
154
|
+
| `hideOnBlur` | `boolean` | `true` | Close the listbox on blur |
|
|
155
|
+
| `className` | `string` | — | Extra class on the root |
|
|
156
156
|
|
|
157
157
|
Any other native `<input>` prop (e.g. `placeholder`, `required`, `disabled`) is passed through to the `<input>`.
|
|
158
158
|
|
|
@@ -165,7 +165,7 @@ Any other native `<input>` prop (e.g. `placeholder`, `required`, `disabled`) is
|
|
|
165
165
|
|
|
166
166
|
## Modifiers
|
|
167
167
|
|
|
168
|
-
This component has no BEM modifier classes — its
|
|
168
|
+
This component has no BEM modifier classes — its border states come from the shared validation rules in `Form/form.css`: `aria-invalid="true"` for explicit errors, and `:user-valid` / `:user-invalid` once `mx-validate` is added to the `<input>` (Twig, via `attributes`) or the `.mx-autocomplete` wrapper (React, via `className`).
|
|
169
169
|
|
|
170
170
|
---
|
|
171
171
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
exports[`Autocomplete 1`] = `
|
|
4
4
|
"
|
|
5
5
|
<mx-autocomplete class="mx-autocomplete">
|
|
6
|
-
<div class="mx-autocomplete__control mx-form--inline-button">
|
|
6
|
+
<div class="mx-autocomplete__control mx-form--inline-button" data-control="" aria-busy="false">
|
|
7
7
|
<input class="mx-input__text" id="autocomplete-fruit" name="unique-0" type="text" role="combobox" aria-expanded="false" aria-controls="unique-0" aria-autocomplete="list" aria-activedescendant="" aria-describedby="unique-0" aria-label="Choose a fruit" autocomplete="off" placeholder="Start typing a fruit…">
|
|
8
8
|
</div>
|
|
9
9
|
<div class="mx-autocomplete__suggestions">
|
|
@@ -18,8 +18,8 @@ exports[`Autocomplete 1`] = `
|
|
|
18
18
|
exports[`Invalid 1`] = `
|
|
19
19
|
"
|
|
20
20
|
<mx-autocomplete class="mx-autocomplete">
|
|
21
|
-
<div class="mx-autocomplete__control mx-form--inline-button">
|
|
22
|
-
<input class="mx-input__text
|
|
21
|
+
<div class="mx-autocomplete__control mx-form--inline-button" data-control="">
|
|
22
|
+
<input class="mx-input__text" id="autocomplete-fruit" name="unique-0" type="text" role="combobox" aria-expanded="false" aria-controls="unique-0" aria-autocomplete="list" aria-activedescendant="" aria-describedby="unique-0" aria-label="Choose a fruit" autocomplete="off" placeholder="Start typing a fruit…" aria-invalid="true">
|
|
23
23
|
</div>
|
|
24
24
|
<div class="mx-autocomplete__suggestions">
|
|
25
25
|
|
|
@@ -31,10 +31,29 @@ exports[`Invalid 1`] = `
|
|
|
31
31
|
"
|
|
32
32
|
`;
|
|
33
33
|
|
|
34
|
+
exports[`Pending 1`] = `
|
|
35
|
+
"
|
|
36
|
+
<mx-autocomplete class="mx-autocomplete">
|
|
37
|
+
<div class="mx-autocomplete__control mx-form--inline-button" data-control="" aria-busy="false">
|
|
38
|
+
<input class="mx-input__text" id="autocomplete-fruit" name="unique-0" type="search" role="combobox" aria-expanded="true" aria-controls="unique-0" aria-autocomplete="list" aria-activedescendant="" aria-describedby="unique-0" aria-label="Choose a fruit" autocomplete="off" placeholder="Start typing a fruit…">
|
|
39
|
+
<button class="mx-button mx-button--icon-only" type="button">
|
|
40
|
+
<span class="mx-icon mx-icon--search" aria-hidden="true"></span>
|
|
41
|
+
<span class="sr-only">Search</span>
|
|
42
|
+
</button>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="mx-autocomplete__suggestions">
|
|
45
|
+
|
|
46
|
+
<ul class="mx-autocomplete__listbox" id="unique-0" role="listbox"><li class="mx-autocomplete__option" id="autocomplete-fruit-option-0" role="option" aria-selected="false" data-value="blueberry">Blueberry</li><li class="mx-autocomplete__option" id="autocomplete-fruit-option-1" role="option" aria-selected="false" data-value="plum">Plum</li></ul>
|
|
47
|
+
<output class="sr-only" aria-live="polite" data-autocomplete-status="">2 results available</output>
|
|
48
|
+
</div>
|
|
49
|
+
</mx-autocomplete>
|
|
50
|
+
"
|
|
51
|
+
`;
|
|
52
|
+
|
|
34
53
|
exports[`Required 1`] = `
|
|
35
54
|
"
|
|
36
55
|
<mx-autocomplete class="mx-autocomplete">
|
|
37
|
-
<div class="mx-autocomplete__control mx-form--inline-button">
|
|
56
|
+
<div class="mx-autocomplete__control mx-form--inline-button" data-control="">
|
|
38
57
|
<input class="mx-input__text" id="autocomplete-fruit" name="unique-0" type="text" role="combobox" aria-expanded="false" aria-controls="unique-0" aria-autocomplete="list" aria-activedescendant="" aria-describedby="unique-0" aria-label="Choose a fruit" autocomplete="off" placeholder="Start typing a fruit…" required="">
|
|
39
58
|
</div>
|
|
40
59
|
<div class="mx-autocomplete__suggestions">
|
|
@@ -47,10 +66,25 @@ exports[`Required 1`] = `
|
|
|
47
66
|
"
|
|
48
67
|
`;
|
|
49
68
|
|
|
69
|
+
exports[`Screen Reader Announcements 1`] = `
|
|
70
|
+
"
|
|
71
|
+
<mx-autocomplete class="mx-autocomplete">
|
|
72
|
+
<div class="mx-autocomplete__control mx-form--inline-button" data-control="" aria-busy="true">
|
|
73
|
+
<input class="mx-input__text" id="autocomplete-fruit" name="unique-0" type="text" role="combobox" aria-expanded="false" aria-controls="unique-0" aria-autocomplete="list" aria-activedescendant="" aria-describedby="unique-0" aria-label="Choose a fruit" autocomplete="off" placeholder="Start typing a fruit…">
|
|
74
|
+
</div>
|
|
75
|
+
<div class="mx-autocomplete__suggestions">
|
|
76
|
+
|
|
77
|
+
<ul class="mx-autocomplete__listbox" id="unique-0" role="listbox" hidden=""><li class="mx-autocomplete__option" id="autocomplete-fruit-option-0" role="option" aria-selected="false" data-value="blueberry">Blueberry</li><li class="mx-autocomplete__option" id="autocomplete-fruit-option-1" role="option" aria-selected="false" data-value="plum">Plum</li></ul>
|
|
78
|
+
<output class="sr-only" aria-live="polite" data-autocomplete-status=""></output>
|
|
79
|
+
</div>
|
|
80
|
+
</mx-autocomplete>
|
|
81
|
+
"
|
|
82
|
+
`;
|
|
83
|
+
|
|
50
84
|
exports[`Search 1`] = `
|
|
51
85
|
"
|
|
52
86
|
<mx-autocomplete class="mx-autocomplete">
|
|
53
|
-
<div class="mx-autocomplete__control mx-form--inline-button">
|
|
87
|
+
<div class="mx-autocomplete__control mx-form--inline-button" data-control="">
|
|
54
88
|
<input class="mx-input__text" id="autocomplete-fruit" name="unique-0" type="search" role="combobox" aria-expanded="false" aria-controls="unique-0" aria-autocomplete="list" aria-activedescendant="" aria-describedby="unique-0" aria-label="Choose a fruit" autocomplete="off" placeholder="Start typing a fruit…">
|
|
55
89
|
<button class="mx-button mx-button--icon-only" type="button">
|
|
56
90
|
<span class="mx-icon mx-icon--search" aria-hidden="true"></span>
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
|
-
exports[`Autocomplete 1`] = `"<div class="mx-autocomplete"><div class="mx-autocomplete__control mx-form--inline-button"><input placeholder="Start typing a fruit…" id="autocomplete-fruit" role="combobox" class="mx-input__text" autocomplete="off" aria-expanded="false" aria-controls="autocomplete-fruit-listbox" aria-autocomplete="list" aria-label="Choose a fruit" aria-describedby="help-autocomplete-fruit" aria-invalid="false" type="text" value="" name="fruit"></div><div class="mx-autocomplete__suggestions"><ul id="autocomplete-fruit-listbox" role="listbox" class="mx-autocomplete__listbox" hidden=""></ul><output class="sr-only" aria-live="polite"></output></div></div>"`;
|
|
3
|
+
exports[`Autocomplete 1`] = `"<div class="mx-autocomplete"><div class="mx-autocomplete__control mx-form--inline-button" aria-busy="false"><input placeholder="Start typing a fruit…" id="autocomplete-fruit" role="combobox" class="mx-input__text" autocomplete="off" aria-expanded="false" aria-controls="autocomplete-fruit-listbox" aria-autocomplete="list" aria-label="Choose a fruit" aria-describedby="help-autocomplete-fruit" aria-invalid="false" type="text" value="" name="fruit"></div><div class="mx-autocomplete__suggestions"><ul id="autocomplete-fruit-listbox" role="listbox" class="mx-autocomplete__listbox" hidden=""></ul><output class="sr-only" aria-live="polite"></output></div></div>"`;
|
|
4
4
|
|
|
5
|
-
exports[`Invalid 1`] = `"<div class="mx-autocomplete"><div class="mx-autocomplete__control mx-form--inline-button"><input placeholder="Start typing a fruit…" id="autocomplete-fruit" role="combobox" class="mx-input__text
|
|
5
|
+
exports[`Invalid 1`] = `"<div class="mx-autocomplete"><div class="mx-autocomplete__control mx-form--inline-button" aria-busy="false"><input placeholder="Start typing a fruit…" id="autocomplete-fruit" role="combobox" class="mx-input__text" autocomplete="off" aria-expanded="false" aria-controls="autocomplete-fruit-listbox" aria-autocomplete="list" aria-label="Choose a fruit" aria-describedby="help-autocomplete-fruit" aria-invalid="true" type="text" value="" name="fruit"></div><div class="mx-autocomplete__suggestions"><ul id="autocomplete-fruit-listbox" role="listbox" class="mx-autocomplete__listbox" hidden=""></ul><output class="sr-only" aria-live="polite"></output></div></div>"`;
|
|
6
6
|
|
|
7
|
-
exports[`
|
|
7
|
+
exports[`Pending 1`] = `"<div class="mx-autocomplete"><div class="mx-autocomplete__control mx-form--inline-button" aria-busy="false"><input placeholder="Start typing a fruit…" id="autocomplete-fruit" role="combobox" class="mx-input__text" autocomplete="off" aria-expanded="true" aria-controls="autocomplete-fruit-listbox" aria-autocomplete="list" aria-label="Choose a fruit" aria-describedby="help-autocomplete-fruit" aria-invalid="false" type="text" value="lu" name="fruit"></div><div class="mx-autocomplete__suggestions"><ul id="autocomplete-fruit-listbox" role="listbox" class="mx-autocomplete__listbox"><li id="autocomplete-fruit-option-0" role="option" aria-selected="false" class="mx-autocomplete__option">Blueberry</li><li id="autocomplete-fruit-option-1" role="option" aria-selected="false" class="mx-autocomplete__option">Plum</li></ul><output class="sr-only" aria-live="polite">2 results available</output></div></div>"`;
|
|
8
8
|
|
|
9
|
-
exports[`
|
|
9
|
+
exports[`Required 1`] = `"<div class="mx-autocomplete"><div class="mx-autocomplete__control mx-form--inline-button" aria-busy="false"><input placeholder="Start typing a fruit…" required="" id="autocomplete-fruit" role="combobox" class="mx-input__text" autocomplete="off" aria-expanded="false" aria-controls="autocomplete-fruit-listbox" aria-autocomplete="list" aria-label="Choose a fruit" aria-describedby="help-autocomplete-fruit" aria-invalid="false" type="text" value="" name="fruit"></div><div class="mx-autocomplete__suggestions"><ul id="autocomplete-fruit-listbox" role="listbox" class="mx-autocomplete__listbox" hidden=""></ul><output class="sr-only" aria-live="polite"></output></div></div>"`;
|
|
10
|
+
|
|
11
|
+
exports[`Screen Reader Announcements 1`] = `"<div class="mx-autocomplete"><div class="mx-autocomplete__control mx-form--inline-button" aria-busy="false"><input placeholder="Start typing a fruit…" id="autocomplete-fruit" role="combobox" class="mx-input__text" autocomplete="off" aria-expanded="false" aria-controls="autocomplete-fruit-listbox" aria-autocomplete="list" aria-label="Choose a fruit" aria-describedby="help-autocomplete-fruit" aria-invalid="false" type="text" value="" name="fruit"></div><div class="mx-autocomplete__suggestions"><ul id="autocomplete-fruit-listbox" role="listbox" class="mx-autocomplete__listbox" hidden=""></ul><output class="sr-only" aria-live="polite"></output></div></div>"`;
|
|
12
|
+
|
|
13
|
+
exports[`Search 1`] = `"<div class="mx-autocomplete"><div class="mx-autocomplete__control mx-form--inline-button" aria-busy="false"><input placeholder="Start typing a fruit…" id="autocomplete-fruit" role="combobox" class="mx-input__text" autocomplete="off" aria-expanded="false" aria-controls="autocomplete-fruit-listbox" aria-autocomplete="list" aria-label="Choose a fruit" aria-describedby="help-autocomplete-fruit" aria-invalid="false" type="search" value="" name="fruit"><button class="mx-button mx-button--icon-only" type="button"><span class="mx-icon mx-icon--search" aria-hidden="true"></span><span class="sr-only">Search</span></button></div><div class="mx-autocomplete__suggestions"><ul id="autocomplete-fruit-listbox" role="listbox" class="mx-autocomplete__listbox" hidden=""></ul><output class="sr-only" aria-live="polite"></output></div></div>"`;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
max-inline-size: var(--container-max-width);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
/* @public --autocomplete-background --autocomplete-foreground --autocomplete-radius --autocomplete-shadow --autocomplete-max-height --autocomplete-padding-inline --autocomplete-padding-block */
|
|
17
|
+
/* @public --autocomplete-background --autocomplete-foreground --autocomplete-radius --autocomplete-shadow --autocomplete-max-height --autocomplete-padding-inline --autocomplete-padding-block --autocomplete-line-width --autocomplete-line-colour */
|
|
18
18
|
.mx-autocomplete__listbox {
|
|
19
19
|
position: absolute;
|
|
20
20
|
z-index: 10;
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
margin: 0;
|
|
24
24
|
list-style: none;
|
|
25
25
|
background-color: var(--autocomplete-background, var(--colour-background));
|
|
26
|
+
border: var(--autocomplete-line-width, 1px) solid var(--autocomplete-line-colour, transparent);
|
|
26
27
|
color: var(--autocomplete-foreground, var(--colour-foreground));
|
|
27
28
|
border-radius: var(--autocomplete-radius, var(--border-radius));
|
|
28
29
|
box-shadow: var(--autocomplete-shadow, var(--box-shadow));
|
|
@@ -57,4 +58,14 @@
|
|
|
57
58
|
outline-offset: var(--outline-offset, -2px);
|
|
58
59
|
}
|
|
59
60
|
}
|
|
61
|
+
|
|
62
|
+
.mx-autocomplete__control[aria-busy] {
|
|
63
|
+
& button {
|
|
64
|
+
order: 3;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
&::after {
|
|
68
|
+
order: 2;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
60
71
|
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
{% set classes = [
|
|
2
2
|
'mx-input__text',
|
|
3
|
-
status == "invalid" ? "error" : null,
|
|
4
|
-
status == "valid" ? "success" : null,
|
|
5
3
|
] %}
|
|
6
4
|
{% set attributes = (attributes ?? create_attribute()).addClass(classes) %}
|
|
7
5
|
{% set status = status|default("default") %}
|
|
8
6
|
|
|
9
7
|
<mx-autocomplete class="mx-autocomplete"{% if noResultsLabel %} data-no-results-label="{{ noResultsLabel }}"{% endif %}>
|
|
10
|
-
<div class="mx-autocomplete__control mx-form--inline-button">
|
|
8
|
+
<div class="mx-autocomplete__control mx-form--inline-button" data-control>
|
|
11
9
|
<input{{ attributes }}
|
|
12
10
|
id="{{ id }}"
|
|
13
11
|
name="{{ name }}"
|
|
@@ -51,10 +51,7 @@ const Checkbox = ({
|
|
|
51
51
|
const state = use(CheckboxContext)
|
|
52
52
|
const { inputProps } = useCheckboxGroupItem(props, state, ref)
|
|
53
53
|
|
|
54
|
-
const classes = classNames("mx-checkbox", className
|
|
55
|
-
error: status === FormStatus.INVALID,
|
|
56
|
-
success: status === FormStatus.VALID,
|
|
57
|
-
})
|
|
54
|
+
const classes = classNames("mx-checkbox", className)
|
|
58
55
|
|
|
59
56
|
return (
|
|
60
57
|
<div className={classes}>
|
|
@@ -81,10 +78,7 @@ const SingleCheckbox = ({
|
|
|
81
78
|
const state = useToggleState(props)
|
|
82
79
|
const { inputProps } = useCheckbox(props, state, ref)
|
|
83
80
|
|
|
84
|
-
const classes = classNames("mx-checkbox", className
|
|
85
|
-
error: status === FormStatus.INVALID,
|
|
86
|
-
success: status === FormStatus.VALID,
|
|
87
|
-
})
|
|
81
|
+
const classes = classNames("mx-checkbox", className)
|
|
88
82
|
|
|
89
83
|
return (
|
|
90
84
|
<div className={classes}>
|
|
@@ -24,8 +24,8 @@ Accessible checkbox and radio group components powered by [react-aria](https://r
|
|
|
24
24
|
checked: true,
|
|
25
25
|
} %}
|
|
26
26
|
|
|
27
|
-
{# Required checkbox with invalid status — adds
|
|
28
|
-
|
|
27
|
+
{# Required checkbox with invalid status — adds aria-invalid (which paints
|
|
28
|
+
the red border), plus aria-describedby pointing at status-{id} #}
|
|
29
29
|
{% include '@mixtape/Form/Checkbox/input-checkbox.twig' with {
|
|
30
30
|
id: 'terms',
|
|
31
31
|
name: 'terms',
|
|
@@ -39,17 +39,17 @@ Accessible checkbox and radio group components powered by [react-aria](https://r
|
|
|
39
39
|
|
|
40
40
|
**input-checkbox.twig props** (composed from `FormControl` in `ids-shape` — checkbox/radio share the same template):
|
|
41
41
|
|
|
42
|
-
| Prop | Type | Required | Description
|
|
43
|
-
| ---------------- | ----------------- | -------- |
|
|
44
|
-
| `id` | `string` | Yes | Input id — also used to derive the `aria-describedby` ids (`help-{id}`, `status-{id}`)
|
|
45
|
-
| `name` | `string` | Yes | `name` attribute on the input
|
|
46
|
-
| `value` | `string` | Yes | `value` attribute on the input
|
|
47
|
-
| `label` | `string` | Yes | Label text rendered inside `<label for="{id}">`
|
|
48
|
-
| `checked` | `boolean` | No | Adds `checked="checked"` to the input
|
|
49
|
-
| `required` | `boolean` | No | Adds the `required` attribute
|
|
50
|
-
| `status` | `FormStatusTypes` | No | `invalid` adds
|
|
51
|
-
| `hasDescription` | `boolean` | No | When `true`, `aria-describedby` is wired up to `help-{id}` (and `status-{id}` when `status` is set)
|
|
52
|
-
| `attributes` | `Attribute` | No | Optional Drupal-style attributes object — `mx-checkbox`
|
|
42
|
+
| Prop | Type | Required | Description |
|
|
43
|
+
| ---------------- | ----------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
44
|
+
| `id` | `string` | Yes | Input id — also used to derive the `aria-describedby` ids (`help-{id}`, `status-{id}`) |
|
|
45
|
+
| `name` | `string` | Yes | `name` attribute on the input |
|
|
46
|
+
| `value` | `string` | Yes | `value` attribute on the input |
|
|
47
|
+
| `label` | `string` | Yes | Label text rendered inside `<label for="{id}">` |
|
|
48
|
+
| `checked` | `boolean` | No | Adds `checked="checked"` to the input |
|
|
49
|
+
| `required` | `boolean` | No | Adds the `required` attribute |
|
|
50
|
+
| `status` | `FormStatusTypes` | No | `invalid` adds `aria-invalid="true"`, which paints the red border. Live `:user-*` colours need `mx-validate` on the wrapper. Defaults to `default` |
|
|
51
|
+
| `hasDescription` | `boolean` | No | When `true`, `aria-describedby` is wired up to `help-{id}` (and `status-{id}` when `status` is set) |
|
|
52
|
+
| `attributes` | `Attribute` | No | Optional Drupal-style attributes object — `mx-checkbox` is always merged on top |
|
|
53
53
|
|
|
54
54
|
The template renders `type="checkbox"` directly — for radio inputs use a sibling template (or hand-author the markup with `mx-radio` on the wrapper and `type="radio"` on the input).
|
|
55
55
|
|
|
@@ -164,11 +164,16 @@ Each input auto-generates its own `id` via `useId()` and wires its `<label htmlF
|
|
|
164
164
|
|
|
165
165
|
## Status states
|
|
166
166
|
|
|
167
|
-
| `status` |
|
|
168
|
-
| -------------------- |
|
|
169
|
-
| `FormStatus.DEFAULT` |
|
|
170
|
-
| `FormStatus.INVALID` | `
|
|
171
|
-
| `FormStatus.VALID` |
|
|
167
|
+
| `status` | Attribute on input | Effect |
|
|
168
|
+
| -------------------- | ---------------------- | ------------------------------------------ |
|
|
169
|
+
| `FormStatus.DEFAULT` | `aria-invalid="false"` | Normal border |
|
|
170
|
+
| `FormStatus.INVALID` | `aria-invalid="true"` | Red border on the input |
|
|
171
|
+
| `FormStatus.VALID` | — | No border change — see `mx-validate` below |
|
|
172
|
+
|
|
173
|
+
Add `mx-validate` to the `.mx-checkbox` wrapper to opt into live
|
|
174
|
+
`:user-valid` / `:user-invalid` border colours as the user interacts. Without
|
|
175
|
+
it, only an explicit `INVALID` status colours the border. See
|
|
176
|
+
[Form/README.md](../README.md#validation-state).
|
|
172
177
|
|
|
173
178
|
## Touch target sizes
|
|
174
179
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/html-vite"
|
|
2
|
+
import Component from "./checkbox-card.twig"
|
|
3
|
+
import "../form.css"
|
|
4
|
+
|
|
5
|
+
type CheckboxCardProps = {
|
|
6
|
+
id: string
|
|
7
|
+
name: string
|
|
8
|
+
value: string
|
|
9
|
+
label: string
|
|
10
|
+
hint?: string
|
|
11
|
+
checked?: boolean
|
|
12
|
+
required?: boolean
|
|
13
|
+
status?: "default" | "invalid" | "valid"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const meta: Meta<CheckboxCardProps> = {
|
|
17
|
+
tags: ["autodocs"],
|
|
18
|
+
component: Component,
|
|
19
|
+
args: {
|
|
20
|
+
id: "pay-carer",
|
|
21
|
+
name: "payments",
|
|
22
|
+
value: "Carer Payment or Allowance",
|
|
23
|
+
label: "Carer Payment or Carer Allowance",
|
|
24
|
+
},
|
|
25
|
+
parameters: {
|
|
26
|
+
a11y: {
|
|
27
|
+
config: {
|
|
28
|
+
rules: [
|
|
29
|
+
{
|
|
30
|
+
// ID's are not unique due to test-runner.
|
|
31
|
+
id: "label",
|
|
32
|
+
enabled: false,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default meta
|
|
41
|
+
type Story = StoryObj<CheckboxCardProps>
|
|
42
|
+
|
|
43
|
+
export const CheckboxCard: Story = {}
|
|
44
|
+
|
|
45
|
+
export const WithHint: Story = {
|
|
46
|
+
args: {
|
|
47
|
+
id: "pay-other",
|
|
48
|
+
value: "Another income support payment",
|
|
49
|
+
label: "Another income support payment",
|
|
50
|
+
hint: "You will be asked which one before you submit",
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const Checked: Story = {
|
|
55
|
+
args: {
|
|
56
|
+
checked: true,
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const Invalid: Story = {
|
|
61
|
+
args: {
|
|
62
|
+
status: "invalid",
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* `.mx-choice-divider` splits a set of card choices into two groups — e.g.
|
|
68
|
+
* "pick one of these — or — pick this other option". Plain markup, not a
|
|
69
|
+
* component prop.
|
|
70
|
+
*/
|
|
71
|
+
export const Divider: Story = {
|
|
72
|
+
render: () =>
|
|
73
|
+
[
|
|
74
|
+
Component({
|
|
75
|
+
id: "card-yes",
|
|
76
|
+
name: "card",
|
|
77
|
+
value: "Yes, I hold a card",
|
|
78
|
+
label: "Yes, I hold a card",
|
|
79
|
+
hint: "Pensioner Concession, Health Care or DVA card",
|
|
80
|
+
}),
|
|
81
|
+
'<div class="mx-choice-divider">or</div>',
|
|
82
|
+
Component({
|
|
83
|
+
id: "card-unsure",
|
|
84
|
+
name: "card",
|
|
85
|
+
value: "Not sure",
|
|
86
|
+
label: "I am not sure",
|
|
87
|
+
hint: "We will ask a few more questions to work it out",
|
|
88
|
+
}),
|
|
89
|
+
].join(""),
|
|
90
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/react-vite"
|
|
2
|
+
import CheckboxCard, { FormCheckboxCard, SingleCheckboxCard } from "./CheckboxCard"
|
|
3
|
+
import "../form.css"
|
|
4
|
+
import { Page } from "../../../.storybook-react/decorators"
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof SingleCheckboxCard> = {
|
|
7
|
+
decorators: [Page],
|
|
8
|
+
component: SingleCheckboxCard,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default meta
|
|
12
|
+
|
|
13
|
+
export const Single: StoryObj<typeof SingleCheckboxCard> = {
|
|
14
|
+
args: {
|
|
15
|
+
children: "Carer Payment or Carer Allowance",
|
|
16
|
+
value: "carer",
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const WithHint: StoryObj<typeof SingleCheckboxCard> = {
|
|
21
|
+
args: {
|
|
22
|
+
children: "Another income support payment",
|
|
23
|
+
hint: "You will be asked which one before you submit",
|
|
24
|
+
value: "other",
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const Group: StoryObj<typeof FormCheckboxCard> = {
|
|
29
|
+
render: ({ children, ...args }) => <FormCheckboxCard {...args}>{children}</FormCheckboxCard>,
|
|
30
|
+
args: {
|
|
31
|
+
label: "Which payments do you currently receive?",
|
|
32
|
+
children: (
|
|
33
|
+
<>
|
|
34
|
+
<CheckboxCard value="age">Age Pension</CheckboxCard>
|
|
35
|
+
<CheckboxCard value="dsp">Disability Support Pension</CheckboxCard>
|
|
36
|
+
<CheckboxCard value="carer">Carer Payment or Carer Allowance</CheckboxCard>
|
|
37
|
+
<CheckboxCard value="other" hint="You will be asked which one before you submit">
|
|
38
|
+
Another income support payment
|
|
39
|
+
</CheckboxCard>
|
|
40
|
+
</>
|
|
41
|
+
),
|
|
42
|
+
},
|
|
43
|
+
}
|