@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
package/src/Form/README.md
CHANGED
|
@@ -32,7 +32,7 @@ The input's `aria-describedby` is automatically wired to `help-{id}` — `FormDe
|
|
|
32
32
|
<div class="mx-form-item">
|
|
33
33
|
<label class="mx-label" for="email">Email address</label>
|
|
34
34
|
<input
|
|
35
|
-
class="mx-input__text
|
|
35
|
+
class="mx-input__text"
|
|
36
36
|
id="email"
|
|
37
37
|
type="email"
|
|
38
38
|
name="email"
|
|
@@ -46,12 +46,13 @@ The input's `aria-describedby` is automatically wired to `help-{id}` — `FormDe
|
|
|
46
46
|
|
|
47
47
|
## Input modifier classes
|
|
48
48
|
|
|
49
|
-
| Class | Effect
|
|
50
|
-
| ------------------------ |
|
|
51
|
-
| `mx-input--wide` | `inline-size: 100%` — fills its container
|
|
52
|
-
| `mx-input--small` | Reduced border (1px), smaller chevron offset
|
|
53
|
-
| `mx-input--icon` | Adds leading icon via `::before` mask
|
|
54
|
-
| `mx-form--inline-button` | Input + button fused into one bordered unit (used in Search)
|
|
49
|
+
| Class | Effect |
|
|
50
|
+
| ------------------------ | ------------------------------------------------------------- |
|
|
51
|
+
| `mx-input--wide` | `inline-size: 100%` — fills its container |
|
|
52
|
+
| `mx-input--small` | Reduced border (1px), smaller chevron offset |
|
|
53
|
+
| `mx-input--icon` | Adds leading icon via `::before` mask |
|
|
54
|
+
| `mx-form--inline-button` | Input + button fused into one bordered unit (used in Search) |
|
|
55
|
+
| `mx-validate` | Opt in to live `:user-valid` / `:user-invalid` border colours |
|
|
55
56
|
|
|
56
57
|
## Form actions
|
|
57
58
|
|
|
@@ -186,13 +187,64 @@ import { FormStatus } from "../../enums"
|
|
|
186
187
|
|
|
187
188
|
---
|
|
188
189
|
|
|
189
|
-
##
|
|
190
|
+
## Validation state
|
|
190
191
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
192
|
+
There is no `error` or `success` class to apply. Two hooks drive input borders:
|
|
193
|
+
|
|
194
|
+
### 1. Live native validation — opt in with `mx-validate`
|
|
195
|
+
|
|
196
|
+
Add `mx-validate` to a control to let the browser colour it as the user types.
|
|
197
|
+
Without the class, a control is **never** coloured automatically — so filling in
|
|
198
|
+
an unmarked field doesn't turn it green.
|
|
199
|
+
|
|
200
|
+
```html
|
|
201
|
+
<input class="mx-input__text mx-validate" type="email" required />
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
For checkbox and radio, put it on the wrapper — that's where `className` and
|
|
205
|
+
Drupal `attributes` land:
|
|
206
|
+
|
|
207
|
+
```html
|
|
208
|
+
<div class="mx-checkbox mx-validate"><input type="checkbox" required /><label>…</label></div>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
| Selector | Effect | When it matches |
|
|
212
|
+
| --------------- | ------------ | -------------------------------------------------------------------- |
|
|
213
|
+
| `:user-valid` | Green border | Field passes validation **and** the user has interacted or submitted |
|
|
214
|
+
| `:user-invalid` | Red border | Field fails validation **and** the user has interacted or submitted |
|
|
215
|
+
|
|
216
|
+
`:user-*` is used rather than `:valid`/`:invalid` so a blank `required` field
|
|
217
|
+
isn't red on page load.
|
|
218
|
+
|
|
219
|
+
### 2. Explicit errors — `aria-invalid`, no opt-in
|
|
220
|
+
|
|
221
|
+
`[aria-invalid="true"]` always paints a red border, with or without
|
|
222
|
+
`mx-validate`. This is for failures the browser can't see: server-rendered
|
|
223
|
+
(Drupal) or async. The consumer has already decided the field is wrong, so
|
|
224
|
+
there's nothing to opt into.
|
|
225
|
+
|
|
226
|
+
Live success styling excludes `[aria-invalid="true"]`, so an explicit error
|
|
227
|
+
stays red even when the field passes native validation.
|
|
228
|
+
|
|
229
|
+
### `status` prop (`FormStatus` enum)
|
|
230
|
+
|
|
231
|
+
`status` no longer sets border classes. It controls the ARIA state and which
|
|
232
|
+
message block renders:
|
|
233
|
+
|
|
234
|
+
| Value | Effect |
|
|
235
|
+
| -------------------- | -------------------------------------------------------------- |
|
|
236
|
+
| `FormStatus.DEFAULT` | `aria-invalid="false"`, no message block |
|
|
237
|
+
| `FormStatus.VALID` | `mx-success-message` block, green icon — **no green border** |
|
|
238
|
+
| `FormStatus.INVALID` | `aria-invalid="true"` (⇒ red border), `mx-error-message` block |
|
|
239
|
+
|
|
240
|
+
For a server-side error, set `status={FormStatus.INVALID}` — the border follows
|
|
241
|
+
from `aria-invalid`. For client-side rules, use native attributes (`required`,
|
|
242
|
+
`pattern`, `type="email"`, `min`/`max`), add `mx-validate`, and let the browser
|
|
243
|
+
do it.
|
|
244
|
+
|
|
245
|
+
Green borders are live-only: there is no ARIA counterpart to `aria-invalid`, so
|
|
246
|
+
an explicitly-set `VALID` status renders the success message without recolouring
|
|
247
|
+
the border.
|
|
196
248
|
|
|
197
249
|
---
|
|
198
250
|
|
|
@@ -40,10 +40,7 @@ const Radio = ({
|
|
|
40
40
|
const state = use(RadioContext)
|
|
41
41
|
const { inputProps } = useRadio(props, state, ref)
|
|
42
42
|
|
|
43
|
-
const classes = classNames("mx-radio", className
|
|
44
|
-
error: status === FormStatus.INVALID,
|
|
45
|
-
success: status === FormStatus.VALID,
|
|
46
|
-
})
|
|
43
|
+
const classes = classNames("mx-radio", className)
|
|
47
44
|
|
|
48
45
|
return (
|
|
49
46
|
<div className={classes}>
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# RadioCard
|
|
2
|
+
|
|
3
|
+
A card-style radio — a full padded, bordered, selectable card instead of a small inline control. Use for a small set of mutually-exclusive options that benefit from a larger tap target and optional secondary hint text (e.g. a high-stakes form question), rather than a dense list of ordinary radios.
|
|
4
|
+
|
|
5
|
+
> **HTML/Twig users:** use native `<input type="radio">` with both the `.mx-radio` and `.mx-choice-card` wrapper classes. The react-aria wiring is React-only.
|
|
6
|
+
|
|
7
|
+
`.mx-choice-card` layers on top of `.mx-radio` rather than replacing it — the base class still supplies input reset/sizing, disabled state, and the spacing between stacked cards in a group; `.mx-choice-card`'s higher cascade layer (`design-system.components` vs. `.mx-radio`'s `design-system.atoms`) overrides only what the card treatment needs to change (position, padding, border).
|
|
8
|
+
|
|
9
|
+
`.mx-choice-card` is shared with `CheckboxCard` — it lives in `src/Form/form.css` alongside the base `.mx-checkbox`/`.mx-radio` rules, not in a per-component CSS file, since the two components' card treatments were identical enough to not warrant separate copies.
|
|
10
|
+
|
|
11
|
+
## CSS Import
|
|
12
|
+
|
|
13
|
+
```css
|
|
14
|
+
@import "@pnx-mixtape/mxds/src/Form/form.css";
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Twig
|
|
20
|
+
|
|
21
|
+
```twig
|
|
22
|
+
{% include '@mixtape/Form/RadioCard/radio-card.twig' with {
|
|
23
|
+
id: 'card-yes',
|
|
24
|
+
name: 'card',
|
|
25
|
+
value: 'yes',
|
|
26
|
+
label: 'Yes, I hold a card',
|
|
27
|
+
hint: 'Pensioner Concession, Health Care or DVA card',
|
|
28
|
+
} %}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**radio-card.twig props:**
|
|
32
|
+
|
|
33
|
+
| Prop | Type | Required | Description |
|
|
34
|
+
| ------------ | ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
35
|
+
| `id` | `string` | Yes | Input id |
|
|
36
|
+
| `name` | `string` | Yes | `name` attribute on the input |
|
|
37
|
+
| `value` | `string` | Yes | `value` attribute on the input |
|
|
38
|
+
| `label` | `string` | Yes | Label text rendered inside `<label for="{id}">` |
|
|
39
|
+
| `hint` | `string` | No | Secondary line rendered under the label, inside the card |
|
|
40
|
+
| `checked` | `boolean` | No | Adds `checked="checked"` to the input |
|
|
41
|
+
| `required` | `boolean` | No | Adds the `required` attribute |
|
|
42
|
+
| `status` | `FormStatusTypes` | No | `invalid` adds the `error` class and `aria-invalid="true"`; `valid` adds the `success` class. Defaults to `default` |
|
|
43
|
+
| `attributes` | `Attribute` | No | Optional Drupal-style attributes object — `mx-radio mx-choice-card` (and the status class) is always merged on top |
|
|
44
|
+
|
|
45
|
+
For a group of cards, compose several `radio-card.twig` includes inside a `<fieldset>` — see HTML below.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## HTML
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<fieldset class="mx-form-item mx-fieldset mx-fieldset--plain">
|
|
53
|
+
<legend class="mx-legend">Do you hold a current concession card?</legend>
|
|
54
|
+
|
|
55
|
+
<div class="mx-radio mx-choice-card">
|
|
56
|
+
<input type="radio" id="card-yes" name="card" value="yes" />
|
|
57
|
+
<label for="card-yes">
|
|
58
|
+
Yes, I hold a card
|
|
59
|
+
<span class="mx-choice-card__hint">Pensioner Concession, Health Care or DVA card</span>
|
|
60
|
+
</label>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div class="mx-radio mx-choice-card">
|
|
64
|
+
<input type="radio" id="card-no" name="card" value="no" />
|
|
65
|
+
<label for="card-no">
|
|
66
|
+
No
|
|
67
|
+
<span class="mx-choice-card__hint">You may still be eligible based on your income</span>
|
|
68
|
+
</label>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div class="mx-choice-divider">or</div>
|
|
72
|
+
|
|
73
|
+
<div class="mx-radio mx-choice-card">
|
|
74
|
+
<input type="radio" id="card-unsure" name="card" value="unsure" />
|
|
75
|
+
<label for="card-unsure">I am not sure</label>
|
|
76
|
+
</div>
|
|
77
|
+
</fieldset>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`.mx-choice-divider` is also defined in `src/Form/form.css` — plain markup used to split either card type into two groups, already available once you import `form.css`. See [`CheckboxCard`'s README](../CheckboxCard/README.md#or-divider-between-two-option-groups) for more.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## React
|
|
85
|
+
|
|
86
|
+
Use `FormRadioCard` as the group wrapper and `RadioCard` for each option — same pattern as `FormRadio`/`Radio`. There's no standalone/single variant (a lone radio isn't a meaningful control on its own, same as `Radio`).
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
import { FormRadioCard, RadioCard } from "@pnx-mixtape/mxds/react"
|
|
90
|
+
|
|
91
|
+
;<FormRadioCard label="Do you hold a current concession card?" onChange={setSelected}>
|
|
92
|
+
<RadioCard value="yes" hint="Pensioner Concession, Health Care or DVA card">
|
|
93
|
+
Yes, I hold a card
|
|
94
|
+
</RadioCard>
|
|
95
|
+
<RadioCard value="no" hint="You may still be eligible based on your income">
|
|
96
|
+
No
|
|
97
|
+
</RadioCard>
|
|
98
|
+
</FormRadioCard>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**`FormRadioCard` props:** all `AriaRadioGroupProps` from react-aria + `label: string`
|
|
102
|
+
|
|
103
|
+
**`RadioCard` props:** all `AriaRadioProps` + `hint?: string`, `status?: FormStatus`, `className?: string`
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
### React ⇄ Twig parity
|
|
108
|
+
|
|
109
|
+
Same intentional divergence as `Radio`/`Checkbox`/`CheckboxCard`:
|
|
110
|
+
|
|
111
|
+
- Twig's `label` becomes React `children` — react-aria composes the accessible name from rendered content, not a string prop.
|
|
112
|
+
- Twig's `id`/`name`/`checked`/`required`/`value` are handled by the react-aria hooks (`useRadio`/`useRadioGroup`) via prop spread rather than declared explicitly.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Modifiers
|
|
117
|
+
|
|
118
|
+
No BEM modifier classes — `error`/`success` are applied as plain (unprefixed) status classes, matching `Radio`'s convention, driven by the `status` prop/Twig var.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Accessibility
|
|
123
|
+
|
|
124
|
+
- The input stays a real, focusable `<input type="radio">` — only its default appearance is replaced (`appearance: none` plus a custom checked-state dot), so it keeps native radio semantics, keyboard support (arrow keys to move within the group, per the browser's native radio-group behaviour), and form submission behaviour.
|
|
125
|
+
- The whole card is clickable because the `<label>` fills it — the input itself only needs to be as large as `--control-size` dictates, not the full card.
|
|
126
|
+
- The focus ring (`:focus-visible`) renders on the input itself, inside the card, rather than around the whole card.
|
|
127
|
+
- `hint` text is inside the same `<label>` as the primary text, so both are announced together when the control receives focus — don't rely on `hint` to convey anything the primary `label` text doesn't already establish.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Customisation
|
|
132
|
+
|
|
133
|
+
| Custom property | Applies to | Default |
|
|
134
|
+
| ------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------- |
|
|
135
|
+
| `--choice-padding-block` | `.mx-choice-card` | `var(--spacing-s)` |
|
|
136
|
+
| `--choice-padding-inline` | `.mx-choice-card` | `var(--spacing-m)` |
|
|
137
|
+
| `--choice-colour-active` | `.mx-choice-card`'s border/background tint when checked | `var(--colour-primary)` |
|
|
138
|
+
| `--radio-colour` | The checked dot itself — inherited from `.mx-radio`, not `.mx-choice-card` | `var(--colour-primary)` |
|
|
139
|
+
| `--control-size` | `.mx-choice-card input`, and `.mx-radio`'s own input styling | `var(--spacing-m)` (shared with `Checkbox`/`Radio`) |
|
|
140
|
+
| `--line-width` | `.mx-choice-card`'s border, and `.mx-radio`'s own input border | `2px` |
|
|
141
|
+
|
|
142
|
+
```css
|
|
143
|
+
.theme--health-services .mx-choice-card {
|
|
144
|
+
--choice-colour-active: var(--colour-primary);
|
|
145
|
+
}
|
|
146
|
+
```
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/html-vite"
|
|
2
|
+
import Component from "../FormItem/form-item.twig"
|
|
3
|
+
import InputRadioCard from "./radio-card.twig"
|
|
4
|
+
import Label from "../Label/label.twig"
|
|
5
|
+
import "../form.css"
|
|
6
|
+
import { FormItem as FormItemType } from "@pnx-mixtape/ids-shape"
|
|
7
|
+
|
|
8
|
+
type MxFormItemType = Omit<FormItemType, "fields"> & {
|
|
9
|
+
fields?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const meta: Meta<MxFormItemType> = {
|
|
13
|
+
tags: ["autodocs"],
|
|
14
|
+
component: Component,
|
|
15
|
+
args: {
|
|
16
|
+
id: "card-set",
|
|
17
|
+
as: "fieldset",
|
|
18
|
+
label: Label({
|
|
19
|
+
title: "Do you hold a current concession card?",
|
|
20
|
+
as: "legend",
|
|
21
|
+
}),
|
|
22
|
+
fields: [
|
|
23
|
+
InputRadioCard({
|
|
24
|
+
id: "card-yes",
|
|
25
|
+
name: "card",
|
|
26
|
+
label: "Yes, I hold a card",
|
|
27
|
+
hint: "Pensioner Concession, Health Care or DVA card",
|
|
28
|
+
value: "yes",
|
|
29
|
+
}),
|
|
30
|
+
InputRadioCard({
|
|
31
|
+
id: "card-applied",
|
|
32
|
+
name: "card",
|
|
33
|
+
label: "I have applied but not received it",
|
|
34
|
+
hint: "You can continue, but we may ask for evidence later",
|
|
35
|
+
value: "applied",
|
|
36
|
+
}),
|
|
37
|
+
InputRadioCard({
|
|
38
|
+
id: "card-no",
|
|
39
|
+
name: "card",
|
|
40
|
+
label: "No",
|
|
41
|
+
hint: "You may still be eligible based on your income",
|
|
42
|
+
value: "no",
|
|
43
|
+
}),
|
|
44
|
+
'<div class="mx-choice-divider">or</div>',
|
|
45
|
+
InputRadioCard({
|
|
46
|
+
id: "card-unsure",
|
|
47
|
+
name: "card",
|
|
48
|
+
label: "I am not sure",
|
|
49
|
+
hint: "We will ask a few more questions to work it out",
|
|
50
|
+
value: "unsure",
|
|
51
|
+
}),
|
|
52
|
+
].join(""),
|
|
53
|
+
},
|
|
54
|
+
parameters: {
|
|
55
|
+
deepControls: { enabled: true },
|
|
56
|
+
a11y: {
|
|
57
|
+
config: {
|
|
58
|
+
rules: [
|
|
59
|
+
{
|
|
60
|
+
// ID's are not unique due to test-runner.
|
|
61
|
+
id: "label",
|
|
62
|
+
enabled: false,
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export default meta
|
|
71
|
+
type Story = StoryObj<MxFormItemType>
|
|
72
|
+
|
|
73
|
+
export const RadioCard: Story = {}
|
|
74
|
+
|
|
75
|
+
export const Checked: Story = {
|
|
76
|
+
args: {
|
|
77
|
+
fields: [
|
|
78
|
+
InputRadioCard({
|
|
79
|
+
id: "card-yes",
|
|
80
|
+
name: "card",
|
|
81
|
+
label: "Yes, I hold a card",
|
|
82
|
+
hint: "Pensioner Concession, Health Care or DVA card",
|
|
83
|
+
value: "yes",
|
|
84
|
+
checked: true,
|
|
85
|
+
}),
|
|
86
|
+
InputRadioCard({
|
|
87
|
+
id: "card-no",
|
|
88
|
+
name: "card",
|
|
89
|
+
label: "No",
|
|
90
|
+
hint: "You may still be eligible based on your income",
|
|
91
|
+
value: "no",
|
|
92
|
+
}),
|
|
93
|
+
].join(""),
|
|
94
|
+
},
|
|
95
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/react-vite"
|
|
2
|
+
import RadioCard, { FormRadioCard } from "./RadioCard"
|
|
3
|
+
import { Page } from "../../../.storybook-react/decorators"
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof RadioCard> = {
|
|
6
|
+
decorators: [Page],
|
|
7
|
+
component: RadioCard,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default meta
|
|
11
|
+
export const RadioCards: StoryObj<typeof FormRadioCard> = {
|
|
12
|
+
render: ({ children, ...args }) => <FormRadioCard {...args}>{children}</FormRadioCard>,
|
|
13
|
+
args: {
|
|
14
|
+
label: "Do you hold a current concession card?",
|
|
15
|
+
children: (
|
|
16
|
+
<>
|
|
17
|
+
<RadioCard value="yes" hint="Pensioner Concession, Health Care or DVA card">
|
|
18
|
+
Yes, I hold a card
|
|
19
|
+
</RadioCard>
|
|
20
|
+
<RadioCard value="no" hint="You may still be eligible based on your income">
|
|
21
|
+
No
|
|
22
|
+
</RadioCard>
|
|
23
|
+
</>
|
|
24
|
+
),
|
|
25
|
+
},
|
|
26
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { JSX, PropsWithChildren, useRef, createContext, use, useId } from "react"
|
|
2
|
+
import { useRadio, useRadioGroup, AriaRadioProps, AriaRadioGroupProps } from "react-aria"
|
|
3
|
+
import { useRadioGroupState, RadioGroupState } from "react-stately"
|
|
4
|
+
import classNames from "classnames"
|
|
5
|
+
import FormItem from "../FormItem/FormItem"
|
|
6
|
+
import { FormStatus } from "../../enums"
|
|
7
|
+
|
|
8
|
+
const RadioCardContext = createContext<RadioGroupState>(null)
|
|
9
|
+
|
|
10
|
+
type FormRadioCardProps = PropsWithChildren &
|
|
11
|
+
AriaRadioGroupProps & {
|
|
12
|
+
label?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const FormRadioCard = ({ label, children, ...props }: FormRadioCardProps): JSX.Element => {
|
|
16
|
+
const state = useRadioGroupState(props)
|
|
17
|
+
const { radioGroupProps } = useRadioGroup(props, state)
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<FormItem fieldset {...radioGroupProps} legend={label}>
|
|
21
|
+
<RadioCardContext value={state}>{children}</RadioCardContext>
|
|
22
|
+
</FormItem>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type RadioCardProps = PropsWithChildren &
|
|
27
|
+
AriaRadioProps & {
|
|
28
|
+
hint?: string
|
|
29
|
+
status?: FormStatus
|
|
30
|
+
className?: string
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const RadioCard = ({
|
|
34
|
+
children,
|
|
35
|
+
hint = null,
|
|
36
|
+
status = FormStatus.DEFAULT,
|
|
37
|
+
className = "",
|
|
38
|
+
...props
|
|
39
|
+
}: RadioCardProps): JSX.Element => {
|
|
40
|
+
const id = useId()
|
|
41
|
+
const ref = useRef<HTMLInputElement>(null)
|
|
42
|
+
const state = use(RadioCardContext)
|
|
43
|
+
const { inputProps } = useRadio(props, state, ref)
|
|
44
|
+
|
|
45
|
+
const classes = classNames("mx-radio", "mx-choice-card", className)
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div className={classes}>
|
|
49
|
+
<input id={id} {...inputProps} ref={ref} aria-invalid={status === FormStatus.INVALID} />
|
|
50
|
+
<label htmlFor={id}>
|
|
51
|
+
{children}
|
|
52
|
+
{hint && <span className="mx-choice-card__hint">{hint}</span>}
|
|
53
|
+
</label>
|
|
54
|
+
</div>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default RadioCard
|
|
59
|
+
export { FormRadioCard }
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`Checked 1`] = `
|
|
4
|
+
"
|
|
5
|
+
<fieldset class="mx-form-item mx-fieldset">
|
|
6
|
+
|
|
7
|
+
<legend class="mx-legend">
|
|
8
|
+
Do you hold a current concession card?
|
|
9
|
+
</legend>
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
<div class="mx-radio mx-choice-card">
|
|
13
|
+
<input id="card-yes" type="radio" name="card" value="yes" checked="checked">
|
|
14
|
+
<label for="card-yes">
|
|
15
|
+
Yes, I hold a card
|
|
16
|
+
<span class="mx-choice-card__hint">Pensioner Concession, Health Care or DVA card</span> </label>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="mx-radio mx-choice-card">
|
|
19
|
+
<input id="card-no" type="radio" name="card" value="no">
|
|
20
|
+
<label for="card-no">
|
|
21
|
+
No
|
|
22
|
+
<span class="mx-choice-card__hint">You may still be eligible based on your income</span> </label>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
</fieldset>
|
|
28
|
+
"
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
exports[`Radio Card 1`] = `
|
|
32
|
+
"
|
|
33
|
+
<fieldset class="mx-form-item mx-fieldset">
|
|
34
|
+
|
|
35
|
+
<legend class="mx-legend">
|
|
36
|
+
Do you hold a current concession card?
|
|
37
|
+
</legend>
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
<div class="mx-radio mx-choice-card">
|
|
41
|
+
<input id="card-yes" type="radio" name="card" value="yes">
|
|
42
|
+
<label for="card-yes">
|
|
43
|
+
Yes, I hold a card
|
|
44
|
+
<span class="mx-choice-card__hint">Pensioner Concession, Health Care or DVA card</span> </label>
|
|
45
|
+
</div>
|
|
46
|
+
<div class="mx-radio mx-choice-card">
|
|
47
|
+
<input id="card-applied" type="radio" name="card" value="applied">
|
|
48
|
+
<label for="card-applied">
|
|
49
|
+
I have applied but not received it
|
|
50
|
+
<span class="mx-choice-card__hint">You can continue, but we may ask for evidence later</span> </label>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="mx-radio mx-choice-card">
|
|
53
|
+
<input id="card-no" type="radio" name="card" value="no">
|
|
54
|
+
<label for="card-no">
|
|
55
|
+
No
|
|
56
|
+
<span class="mx-choice-card__hint">You may still be eligible based on your income</span> </label>
|
|
57
|
+
</div>
|
|
58
|
+
<div class="mx-choice-divider">or</div><div class="mx-radio mx-choice-card">
|
|
59
|
+
<input id="card-unsure" type="radio" name="card" value="unsure">
|
|
60
|
+
<label for="card-unsure">
|
|
61
|
+
I am not sure
|
|
62
|
+
<span class="mx-choice-card__hint">We will ask a few more questions to work it out</span> </label>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
</fieldset>
|
|
68
|
+
"
|
|
69
|
+
`;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`Radio Cards 1`] = `"<fieldset class="mx-form-item mx-fieldset" role="radiogroup" aria-orientation="vertical" id="react-aria-_r_0_"><legend class="mx-legend">Do you hold a current concession card?</legend><div class="mx-radio mx-choice-card"><input id="_r_6_" data-react-aria-pressable="true" tabindex="0" aria-invalid="false" type="radio" value="yes" name="react-aria-_r_5_"><label for="_r_6_">Yes, I hold a card<span class="mx-choice-card__hint">Pensioner Concession, Health Care or DVA card</span></label></div><div class="mx-radio mx-choice-card"><input id="_r_8_" data-react-aria-pressable="true" tabindex="0" aria-invalid="false" type="radio" value="no" name="react-aria-_r_5_"><label for="_r_8_">No<span class="mx-choice-card__hint">You may still be eligible based on your income</span></label></div></fieldset>"`;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{% set classes = [
|
|
2
|
+
'mx-radio',
|
|
3
|
+
'mx-choice-card',
|
|
4
|
+
] %}
|
|
5
|
+
{% set attributes = (attributes ?? create_attribute()).addClass(classes) %}
|
|
6
|
+
<div{{ attributes }}>
|
|
7
|
+
<input
|
|
8
|
+
id="{{ id }}"
|
|
9
|
+
type="radio"
|
|
10
|
+
name="{{ name }}"
|
|
11
|
+
value="{{ value }}"
|
|
12
|
+
{% if checked %} checked="checked"{% endif %}
|
|
13
|
+
{% if status == "invalid" %} aria-invalid="true"{% endif %}
|
|
14
|
+
{% if required %} required{% endif %}
|
|
15
|
+
>
|
|
16
|
+
<label for="{{ id }}">
|
|
17
|
+
{{ label }}
|
|
18
|
+
{% if hint %}<span class="mx-choice-card__hint">{{ hint }}</span>{% endif %}
|
|
19
|
+
</label>
|
|
20
|
+
</div>
|
|
@@ -32,10 +32,7 @@ const FormSelect = ({
|
|
|
32
32
|
const handleChange: ChangeEventHandler<HTMLSelectElement> = ({ currentTarget }) =>
|
|
33
33
|
setInputValue(currentTarget.value)
|
|
34
34
|
|
|
35
|
-
const classes = classNames("mx-input__select", className
|
|
36
|
-
error: status === FormStatus.INVALID,
|
|
37
|
-
success: status === FormStatus.VALID,
|
|
38
|
-
})
|
|
35
|
+
const classes = classNames("mx-input__select", className)
|
|
39
36
|
|
|
40
37
|
const items = options.map(({ label: optionLabel, value }) => (
|
|
41
38
|
<Option label={optionLabel} value={value} key={value} />
|
|
@@ -14,3 +14,17 @@ const meta: Meta<typeof Component> = {
|
|
|
14
14
|
|
|
15
15
|
export default meta
|
|
16
16
|
export const TextInput: StoryObj<typeof Component> = {}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* `mx-validate` opts the input into live native validation — see the Twig
|
|
20
|
+
* `TextInput` stories for the full explanation.
|
|
21
|
+
*/
|
|
22
|
+
export const Validate: StoryObj<typeof Component> = {
|
|
23
|
+
args: {
|
|
24
|
+
type: "email",
|
|
25
|
+
placeholder: "you@example.com",
|
|
26
|
+
"aria-label": "Email address",
|
|
27
|
+
required: true,
|
|
28
|
+
className: "mx-validate",
|
|
29
|
+
},
|
|
30
|
+
}
|
|
@@ -22,10 +22,7 @@ const FormText = ({
|
|
|
22
22
|
const handleChange: ChangeEventHandler<HTMLInputElement> = ({ currentTarget }) =>
|
|
23
23
|
setInputValue(currentTarget.value)
|
|
24
24
|
|
|
25
|
-
const classes = classNames("mx-input__text", className
|
|
26
|
-
error: status === FormStatus.INVALID,
|
|
27
|
-
success: status === FormStatus.VALID,
|
|
28
|
-
})
|
|
25
|
+
const classes = classNames("mx-input__text", className)
|
|
29
26
|
|
|
30
27
|
return (
|
|
31
28
|
<input
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
3
|
exports[`Text Input 1`] = `"<input class="mx-input__text" id="mix-text" aria-describedby="help-mix-text" aria-invalid="false" placeholder="Placeholder" aria-label="Text input" type="text" value="">"`;
|
|
4
|
+
|
|
5
|
+
exports[`Validate 1`] = `"<input class="mx-input__text mx-validate" id="mix-text" required="" aria-describedby="help-mix-text" aria-invalid="false" placeholder="you@example.com" aria-label="Email address" type="email" value="">"`;
|
|
@@ -21,10 +21,7 @@ const FormTextarea = ({
|
|
|
21
21
|
const handleChange: ChangeEventHandler<HTMLTextAreaElement> = ({ currentTarget }) =>
|
|
22
22
|
setInputValue(currentTarget.value)
|
|
23
23
|
|
|
24
|
-
const classes = classNames("mx-input__textarea", className
|
|
25
|
-
error: status === FormStatus.INVALID,
|
|
26
|
-
success: status === FormStatus.VALID,
|
|
27
|
-
})
|
|
24
|
+
const classes = classNames("mx-input__textarea", className)
|
|
28
25
|
|
|
29
26
|
return (
|
|
30
27
|
<textarea
|