@tpzdsp/next-toolkit 2.5.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +22 -13
- package/src/assets/styles/globals.css +75 -95
- package/src/assets/styles/ol.css +57 -16
- package/src/assets/styles/utils.css +80 -0
- package/src/components/Accordion/Accordion.css +85 -0
- package/src/components/Accordion/Accordion.stories.tsx +264 -0
- package/src/components/Accordion/Accordion.tsx +98 -0
- package/src/components/Alert/Alert.css +129 -0
- package/src/components/Alert/Alert.stories.tsx +291 -0
- package/src/components/Alert/Alert.tsx +76 -0
- package/src/components/BackLink/BackLink.css +12 -0
- package/src/components/BackLink/BackLink.stories.tsx +52 -0
- package/src/components/BackLink/BackLink.tsx +44 -0
- package/src/components/BackToTop/BackToTop.css +23 -0
- package/src/components/BackToTop/BackToTop.stories.tsx +41 -0
- package/src/components/BackToTop/BackToTop.tsx +48 -0
- package/src/components/Breadcrumb/Breadcrumb.css +42 -0
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +94 -0
- package/src/components/Breadcrumb/Breadcrumb.tsx +135 -0
- package/src/components/Button/Button.css +229 -0
- package/src/components/Button/Button.stories.tsx +140 -20
- package/src/components/Button/Button.tsx +53 -28
- package/src/components/Button/ButtonSkeleton.stories.tsx +50 -0
- package/src/components/Button/ButtonSkeleton.tsx +14 -0
- package/src/components/ButtonGroup/ButtonGroup.css +52 -0
- package/src/components/ButtonGroup/ButtonGroup.stories.tsx +156 -0
- package/src/components/ButtonGroup/ButtonGroup.tsx +50 -0
- package/src/components/ButtonLink/ButtonLink.css +114 -0
- package/src/components/ButtonLink/ButtonLink.stories.tsx +38 -51
- package/src/components/ButtonLink/ButtonLink.tsx +54 -23
- package/src/components/Card/Card.css +13 -0
- package/src/components/Card/Card.stories.tsx +98 -57
- package/src/components/Card/Card.tsx +4 -13
- package/src/components/CardGroup/CardGroup.css +10 -0
- package/src/components/CardGroup/CardGroup.stories.tsx +81 -0
- package/src/components/CardGroup/CardGroup.tsx +9 -0
- package/src/components/Checkbox/Checkbox.css +49 -0
- package/src/components/Checkbox/Checkbox.stories.tsx +86 -0
- package/src/components/Checkbox/Checkbox.tsx +32 -0
- package/src/components/Chip/Chip.css +54 -0
- package/src/components/Chip/Chip.stories.tsx +94 -0
- package/src/components/Chip/Chip.tsx +34 -0
- package/src/components/CookieBanner/CookieBanner.css +19 -0
- package/src/components/CookieBanner/CookieBanner.stories.tsx +52 -0
- package/src/components/CookieBanner/CookieBanner.tsx +55 -0
- package/src/components/CopyButton/CopyButton.stories.tsx +28 -0
- package/src/components/CopyButton/CopyButton.tsx +65 -0
- package/src/components/DateInput/DateInput.css +13 -0
- package/src/components/DateInput/DateInput.stories.tsx +131 -0
- package/src/components/DateInput/DateInput.test.tsx +21 -0
- package/src/components/DateInput/DateInput.tsx +98 -0
- package/src/components/Details/Details.css +28 -0
- package/src/components/Details/Details.stories.tsx +48 -0
- package/src/components/Details/Details.tsx +41 -0
- package/src/components/Dropdown/Dropdown.css +81 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +131 -0
- package/src/components/Dropdown/Dropdown.tsx +69 -0
- package/src/components/ErrorBoundary/ErrorBoundary.stories.tsx +4 -39
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +7 -4
- package/src/components/ErrorBoundary/ErrorFallback.tsx +32 -66
- package/src/components/ErrorModal/ErrorModal.css +32 -0
- package/src/components/ErrorModal/ErrorModal.stories.tsx +101 -0
- package/src/components/ErrorModal/ErrorModal.tsx +120 -0
- package/src/components/ErrorText/ErrorText.css +22 -0
- package/src/components/ErrorText/ErrorText.stories.tsx +42 -27
- package/src/components/ErrorText/ErrorText.tsx +10 -8
- package/src/components/ExternalLink/ExternalLink.css +12 -0
- package/src/components/ExternalLink/ExternalLink.stories.tsx +43 -0
- package/src/components/ExternalLink/ExternalLink.tsx +43 -0
- package/src/components/Fieldset/Fieldset.css +103 -0
- package/src/components/Fieldset/Fieldset.stories.tsx +304 -0
- package/src/components/Fieldset/Fieldset.tsx +38 -0
- package/src/components/FileUpload/FileUpload.css +85 -0
- package/src/components/FileUpload/FileUpload.stories.tsx +106 -0
- package/src/components/FileUpload/FileUpload.tsx +99 -0
- package/src/components/{layout/footer → Footer}/Copyright.tsx +4 -2
- package/src/components/Footer/Footer.stories.tsx +24 -0
- package/src/components/Footer/Footer.tsx +41 -0
- package/src/components/Footer/Licence.tsx +18 -0
- package/src/components/{layout/footer → Footer}/MetaLinks.tsx +8 -3
- package/src/components/Footer/Small/SmallFooter.tsx +43 -42
- package/src/components/Form/FormGroup.css +18 -0
- package/src/components/Form/FormGroup.stories.tsx +87 -0
- package/src/components/Form/FormGroup.tsx +16 -0
- package/src/components/{layout/header → Header}/Header.stories.tsx +26 -12
- package/src/components/Header/Header.test.tsx +87 -0
- package/src/components/Header/Header.tsx +303 -0
- package/src/components/Header/HeaderAppContent.tsx +120 -0
- package/src/components/Heading/Heading.css +40 -0
- package/src/components/Heading/Heading.stories.tsx +15 -5
- package/src/components/Heading/Heading.tsx +21 -44
- package/src/components/Heading/HeadingSkeleton.stories.tsx +30 -0
- package/src/components/Heading/HeadingSkeleton.tsx +14 -0
- package/src/components/Hero/Hero.css +19 -0
- package/src/components/Hero/Hero.stories.tsx +41 -0
- package/src/components/Hero/Hero.tsx +14 -0
- package/src/components/HintText/HintText.css +5 -0
- package/src/components/HintText/HintText.stories.tsx +29 -0
- package/src/components/HintText/HintText.tsx +13 -0
- package/src/components/InfoBox/InfoBox.css +38 -0
- package/src/components/InfoBox/InfoBox.stories.tsx +51 -403
- package/src/components/InfoBox/InfoBox.tsx +31 -158
- package/src/components/Input/Input.css +77 -0
- package/src/components/Input/Input.stories.tsx +123 -0
- package/src/components/Input/Input.tsx +74 -0
- package/src/components/InputGroup/InputGroup.css +140 -0
- package/src/components/InputGroup/InputGroup.stories.tsx +125 -0
- package/src/components/InputGroup/InputGroup.tsx +47 -0
- package/src/components/InsetText/InsetText.css +5 -0
- package/src/components/InsetText/InsetText.stories.tsx +30 -0
- package/src/components/InsetText/InsetText.tsx +9 -0
- package/src/components/Keyboard/Keyboard.css +9 -0
- package/src/components/Keyboard/Keyboard.stories.tsx +63 -0
- package/src/components/Keyboard/Keyboard.tsx +30 -0
- package/src/components/Label/Label.css +27 -0
- package/src/components/Label/Label.stories.tsx +40 -0
- package/src/components/Label/Label.tsx +17 -0
- package/src/components/LayerSwitcher/LayerSwitcher.css +59 -0
- package/src/components/LayerSwitcher/LayerSwitcher.stories.tsx +112 -0
- package/src/components/LayerSwitcher/LayerSwitcher.tsx +61 -0
- package/src/components/Layout/401/401.stories.tsx +23 -0
- package/src/components/Layout/401/401.tsx +1 -0
- package/src/components/Layout/403/403.stories.tsx +23 -0
- package/src/components/Layout/403/403.tsx +21 -0
- package/src/components/Layout/404/404.stories.tsx +23 -0
- package/src/components/Layout/404/404.tsx +28 -0
- package/src/components/Layout/500/500.stories.tsx +56 -0
- package/src/components/Layout/500/500.tsx +63 -0
- package/src/components/Layout/ButtonGroup/ButtonGroup.css +52 -0
- package/src/components/Layout/ButtonGroup/ButtonGroup.stories.tsx +156 -0
- package/src/components/Layout/ButtonGroup/ButtonGroup.tsx +50 -0
- package/src/components/Layout/HeadingGroup/HeadingGroup.css +21 -0
- package/src/components/Layout/HeadingGroup/HeadingGroup.stories.tsx +84 -0
- package/src/components/Layout/HeadingGroup/HeadingGroup.tsx +9 -0
- package/src/components/Layout/MainWrapper/MainWrapper.css +12 -0
- package/src/components/Layout/MainWrapper/MainWrapper.stories.tsx +36 -0
- package/src/components/Layout/MainWrapper/MainWrapper.tsx +14 -0
- package/src/components/Layout/PageShell/PageShell.css +42 -0
- package/src/components/Layout/PageShell/PageShell.stories.tsx +108 -0
- package/src/components/Layout/PageShell/PageShell.tsx +31 -0
- package/src/components/Layout/ParagraphGroup/ParagraphGroup.css +5 -0
- package/src/components/Layout/ParagraphGroup/ParagraphGroup.stories.tsx +34 -0
- package/src/components/Layout/ParagraphGroup/ParagraphGroup.tsx +9 -0
- package/src/components/Layout/Stack/Stack.css +29 -0
- package/src/components/Layout/Stack/Stack.stories.tsx +83 -0
- package/src/components/Layout/Stack/Stack.tsx +19 -0
- package/src/components/Layout/WidthContainer/WidthContainer.css +17 -0
- package/src/components/Layout/WidthContainer/WidthContainer.stories.tsx +59 -0
- package/src/components/Layout/WidthContainer/WidthContainer.tsx +13 -0
- package/src/components/Legend/Legend.css +95 -0
- package/src/components/Legend/Legend.stories.tsx +81 -0
- package/src/components/Legend/Legend.tsx +32 -0
- package/src/components/Legend/LegendDot.tsx +15 -0
- package/src/components/Legend/LegendPanel.stories.tsx +101 -0
- package/src/components/Legend/LegendPanel.tsx +68 -0
- package/src/components/Legend/LegendSkeleton.stories.tsx +87 -0
- package/src/components/Legend/LegendSkeleton.tsx +73 -0
- package/src/components/LegendSelect/LegendSelect.css +8 -0
- package/src/components/LegendSelect/LegendSelect.stories.tsx +80 -0
- package/src/components/LegendSelect/LegendSelect.tsx +26 -0
- package/src/components/Link/Link.css +98 -0
- package/src/components/Link/Link.stories.tsx +70 -0
- package/src/components/Link/Link.tsx +52 -0
- package/src/components/LinkButton/LinkButton.css +67 -0
- package/src/components/LinkButton/LinkButton.stories.tsx +90 -42
- package/src/components/LinkButton/LinkButton.tsx +50 -63
- package/src/components/LinkList/LinkList.css +28 -0
- package/src/components/LinkList/LinkList.stories.tsx +46 -0
- package/src/components/LinkList/LinkList.tsx +23 -0
- package/src/components/List/Li.tsx +9 -0
- package/src/components/List/List.css +9 -0
- package/src/components/List/OrderedList.stories.tsx +36 -0
- package/src/components/List/OrderedList.tsx +9 -0
- package/src/components/List/UnorderedList.stories.tsx +36 -0
- package/src/components/List/UnorderedList.tsx +9 -0
- package/src/components/LoadingBox/LoadingBox.css +27 -0
- package/src/components/LoadingBox/LoadingBox.stories.tsx +66 -0
- package/src/components/LoadingBox/LoadingBox.tsx +40 -0
- package/src/components/Modal/Modal.css +114 -0
- package/src/components/Modal/Modal.stories.tsx +41 -160
- package/src/components/Modal/Modal.tsx +132 -75
- package/src/components/NoScriptBanner/NoScriptBanner.css +17 -0
- package/src/components/NoScriptBanner/NoScriptBanner.stories.tsx +46 -0
- package/src/components/NoScriptBanner/NoScriptBanner.tsx +26 -0
- package/src/components/Paragraph/Paragraph.css +22 -0
- package/src/components/Paragraph/Paragraph.stories.tsx +1 -42
- package/src/components/Paragraph/Paragraph.tsx +4 -3
- package/src/components/Paragraph/ParagraphSkeleton.stories.tsx +44 -0
- package/src/components/Paragraph/ParagraphSkeleton.tsx +33 -0
- package/src/components/PasswordInput/PasswordInput.css +3 -0
- package/src/components/PasswordInput/PasswordInput.stories.tsx +47 -0
- package/src/components/PasswordInput/PasswordInput.tsx +45 -0
- package/src/components/PhaseBanner/PhaseBanner.css +12 -0
- package/src/components/PhaseBanner/PhaseBanner.stories.tsx +61 -0
- package/src/components/PhaseBanner/PhaseBanner.tsx +17 -0
- package/src/components/Popover/Popover.css +43 -0
- package/src/components/Popover/Popover.stories.tsx +102 -0
- package/src/components/Popover/Popover.tsx +40 -0
- package/src/components/Radio/Radio.css +69 -0
- package/src/components/Radio/Radio.stories.tsx +169 -0
- package/src/components/Radio/Radio.tsx +56 -0
- package/src/components/Resizable/Resizable.css +86 -0
- package/src/components/Resizable/Resizable.stories.tsx +123 -0
- package/src/components/Resizable/Resizable.tsx +86 -0
- package/src/components/ScrollArea/ScrollArea.css +9 -0
- package/src/components/ScrollArea/ScrollArea.stories.tsx +42 -0
- package/src/components/ScrollArea/ScrollArea.tsx +11 -0
- package/src/components/SearchBox/SearchBox.stories.tsx +88 -0
- package/src/components/SearchBox/SearchBox.tsx +36 -0
- package/src/components/Select/AsyncSelect.stories.tsx +84 -0
- package/src/components/Select/AsyncSelect.tsx +41 -0
- package/src/components/Select/Select.css +194 -0
- package/src/components/Select/Select.stories.tsx +162 -0
- package/src/components/Select/Select.test.tsx +36 -0
- package/src/components/Select/Select.tsx +291 -0
- package/src/components/Select/SelectSkeleton.stories.tsx +51 -0
- package/src/components/Select/SelectSkeleton.tsx +23 -0
- package/src/components/Separator/Separator.css +41 -0
- package/src/components/Separator/Separator.stories.tsx +63 -0
- package/src/components/Separator/Separator.tsx +42 -0
- package/src/components/Sidebar/ResizableSidebar.tsx +118 -0
- package/src/components/Sidebar/Sidebar.css +203 -0
- package/src/components/Sidebar/Sidebar.stories.tsx +438 -0
- package/src/components/Sidebar/Sidebar.tsx +225 -0
- package/src/components/Skeleton/Skeleton.css +16 -0
- package/src/components/Skeleton/Skeleton.stories.tsx +39 -0
- package/src/components/Skeleton/Skeleton.tsx +12 -0
- package/src/components/SkipLink/SkipLink.css +16 -0
- package/src/components/SkipLink/SkipLink.stories.tsx +40 -0
- package/src/components/SkipLink/SkipLink.tsx +15 -0
- package/src/components/Spinner/Spinner.css +30 -0
- package/src/components/Spinner/Spinner.stories.tsx +36 -0
- package/src/components/Spinner/Spinner.tsx +45 -0
- package/src/components/StartButton/StartButton.css +13 -0
- package/src/components/StartButton/StartButton.stories.tsx +68 -0
- package/src/components/StartButton/StartButton.tsx +50 -0
- package/src/components/SubmitButton/SubmitButton.stories.tsx +31 -0
- package/src/components/SubmitButton/SubmitButton.tsx +14 -0
- package/src/components/SummaryList/SummaryList.css +71 -0
- package/src/components/SummaryList/SummaryList.stories.tsx +211 -0
- package/src/components/SummaryList/SummaryList.tsx +41 -0
- package/src/components/SummaryList/SummaryListSkeleton.stories.tsx +67 -0
- package/src/components/SummaryList/SummaryListSkeleton.tsx +40 -0
- package/src/components/Tabs/Tabs.css +84 -0
- package/src/components/Tabs/Tabs.stories.tsx +133 -0
- package/src/components/Tabs/Tabs.tsx +66 -0
- package/src/components/Tag/Tag.css +8 -0
- package/src/components/Tag/Tag.stories.tsx +96 -0
- package/src/components/Tag/Tag.tsx +34 -0
- package/src/components/Textarea/Textarea.css +38 -0
- package/src/components/Textarea/Textarea.stories.tsx +131 -0
- package/src/components/Textarea/Textarea.tsx +50 -0
- package/src/components/TextareaCount/TextareaCount.css +17 -0
- package/src/components/TextareaCount/TextareaCount.stories.tsx +131 -0
- package/src/components/TextareaCount/TextareaCount.tsx +108 -0
- package/src/components/Tooltip/Tooltip.css +43 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +110 -0
- package/src/components/Tooltip/Tooltip.tsx +53 -0
- package/src/components/WarningText/WarningText.css +20 -0
- package/src/components/WarningText/WarningText.stories.tsx +29 -0
- package/src/components/WarningText/WarningText.tsx +17 -0
- package/src/components/index.ts +342 -61
- package/src/errors/errorDisplay.ts +70 -0
- package/src/errors/index.ts +1 -0
- package/src/http/constants.ts +1 -0
- package/src/http/fetch.ts +7 -3
- package/src/map/LayerSwitcherPanel.tsx +2 -173
- package/src/map/LegendShim.tsx +2 -0
- package/src/map/MapComponent.tsx +7 -17
- package/src/map/MapControlsOverlay.tsx +68 -175
- package/src/map/Popup.tsx +71 -24
- package/src/map/geocoder/Geocoder.test.tsx +46 -3
- package/src/map/geocoder/Geocoder.tsx +155 -278
- package/src/map/index.ts +1 -1
- package/src/types/utils.ts +0 -10
- package/src/utils/components.ts +96 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/utils.ts +0 -12
- package/src/assets/images/defra-logo.svg +0 -51
- package/src/assets/images/ea-logo.svg +0 -58
- package/src/assets/images/ogl.svg +0 -1
- package/src/components/Button/Button.test.tsx +0 -53
- package/src/components/ButtonLink/ButtonLink.test.tsx +0 -154
- package/src/components/Card/Card.test.tsx +0 -51
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +0 -75
- package/src/components/ErrorBoundary/ErrorFallback.test.tsx +0 -107
- package/src/components/ErrorText/ErrorText.test.tsx +0 -33
- package/src/components/Heading/Heading.test.tsx +0 -22
- package/src/components/Hint/Hint.stories.tsx +0 -58
- package/src/components/Hint/Hint.test.tsx +0 -33
- package/src/components/Hint/Hint.tsx +0 -12
- package/src/components/InfoBox/InfoBox.test.tsx +0 -330
- package/src/components/InfoBox/types.ts +0 -6
- package/src/components/LinkButton/LinkButton.test.tsx +0 -177
- package/src/components/Modal/Modal.test.tsx +0 -246
- package/src/components/NotificationBanner/NotificationBanner.stories.tsx +0 -45
- package/src/components/NotificationBanner/NotificationBanner.test.tsx +0 -58
- package/src/components/NotificationBanner/NotificationBanner.tsx +0 -45
- package/src/components/Paragraph/Paragraph.test.tsx +0 -10
- package/src/components/SlidingPanel/SlidingPanel.stories.tsx +0 -129
- package/src/components/SlidingPanel/SlidingPanel.test.tsx +0 -83
- package/src/components/SlidingPanel/SlidingPanel.tsx +0 -258
- package/src/components/accordion/Accordion.stories.tsx +0 -234
- package/src/components/accordion/Accordion.test.tsx +0 -192
- package/src/components/accordion/Accordion.tsx +0 -73
- package/src/components/backToTop/BackToTop.stories.tsx +0 -407
- package/src/components/backToTop/BackToTop.test.tsx +0 -57
- package/src/components/backToTop/BackToTop.tsx +0 -134
- package/src/components/chip/Chip.stories.tsx +0 -61
- package/src/components/chip/Chip.test.tsx +0 -31
- package/src/components/chip/Chip.tsx +0 -23
- package/src/components/container/Container.tsx +0 -42
- package/src/components/cookieBanner/CookieBanner.stories.tsx +0 -257
- package/src/components/cookieBanner/CookieBanner.test.tsx +0 -68
- package/src/components/cookieBanner/CookieBanner.tsx +0 -73
- package/src/components/divider/RuleDivider.stories.tsx +0 -254
- package/src/components/divider/RuleDivider.test.tsx +0 -164
- package/src/components/divider/RuleDivider.tsx +0 -23
- package/src/components/dropdown/DropdownMenu.test.tsx +0 -211
- package/src/components/dropdown/DropdownMenu.tsx +0 -108
- package/src/components/dropdown/useDropdownMenu.ts +0 -249
- package/src/components/form/Input.stories.tsx +0 -435
- package/src/components/form/Input.test.tsx +0 -206
- package/src/components/form/Input.tsx +0 -23
- package/src/components/form/TextArea.stories.tsx +0 -464
- package/src/components/form/TextArea.test.tsx +0 -232
- package/src/components/form/TextArea.tsx +0 -23
- package/src/components/layout/footer/Footer.tsx +0 -26
- package/src/components/layout/footer/Licence.tsx +0 -19
- package/src/components/layout/header/Header.test.tsx +0 -36
- package/src/components/layout/header/Header.tsx +0 -90
- package/src/components/layout/header/HeaderAuthClient.test.tsx +0 -45
- package/src/components/layout/header/HeaderAuthClient.tsx +0 -40
- package/src/components/layout/header/HeaderNavClient.test.tsx +0 -44
- package/src/components/layout/header/HeaderNavClient.tsx +0 -67
- package/src/components/link/ExternalLink.test.tsx +0 -102
- package/src/components/link/ExternalLink.tsx +0 -29
- package/src/components/link/Link.tsx +0 -26
- package/src/components/select/Select.stories.tsx +0 -336
- package/src/components/select/Select.test.tsx +0 -474
- package/src/components/select/Select.tsx +0 -125
- package/src/components/select/SelectSkeleton.stories.tsx +0 -194
- package/src/components/select/SelectSkeleton.test.tsx +0 -104
- package/src/components/select/SelectSkeleton.tsx +0 -23
- package/src/components/select/common.ts +0 -3
- package/src/components/select/index.ts +0 -18
- package/src/components/skipLink/SkipLink.stories.tsx +0 -346
- package/src/components/skipLink/SkipLink.test.tsx +0 -22
- package/src/components/skipLink/SkipLink.tsx +0 -49
- package/src/map/LegendPanel.tsx +0 -85
- /package/src/{components → assets}/images/DefraLogo.tsx +0 -0
- /package/src/{components → assets}/images/EaLogo.tsx +0 -0
- /package/src/{components → assets}/images/OglLogo.tsx +0 -0
- /package/src/components/{googleAnalytics → GoogleAnalytics}/GlobalVars.tsx +0 -0
- /package/src/components/{googleAnalytics → GoogleAnalytics}/GoogleAnalytics.tsx +0 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
import { Breadcrumb } from './Breadcrumb';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Breadcrumb> = {
|
|
6
|
+
title: 'Components/Breadcrumb',
|
|
7
|
+
component: Breadcrumb,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component: `
|
|
13
|
+
GDS-style breadcrumb: the first (Home) and last (current page) items always show. Unlike GDS's own \`--collapse-on-mobile\`, which only has one all-or-nothing cutoff, middle items collapse one at a time into a static "…" as the screen shrinks, and reveal one at a time as it grows, resize the window (or the Storybook viewport) to see it. No dropdown, the collapsed items aren't individually reachable, this is a purely visual "there's more between these two" indicator.
|
|
14
|
+
|
|
15
|
+
Pass \`items\` as \`{ label, href? }\`. The last item is treated as the current page regardless of whether it has an \`href\` (rendered as plain text with \`aria-current="page"\`, not a link).
|
|
16
|
+
|
|
17
|
+
\`appearance\` defaults to \`"default"\` (dark text, for a normal page background). Pass \`"inverse"\` on a dark background like the Hero, it drives the link colour, the current-page text, and the separator icons together.
|
|
18
|
+
`.trim(),
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default meta;
|
|
25
|
+
|
|
26
|
+
type Story = StoryObj<typeof Breadcrumb>;
|
|
27
|
+
|
|
28
|
+
export const Default: Story = {
|
|
29
|
+
args: {
|
|
30
|
+
items: [
|
|
31
|
+
{ label: 'Home', href: '/' },
|
|
32
|
+
{ label: 'Applications', href: '/applications' },
|
|
33
|
+
{ label: 'Application ABC123' },
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const LongTrail: Story = {
|
|
39
|
+
parameters: {
|
|
40
|
+
docs: {
|
|
41
|
+
description: {
|
|
42
|
+
story:
|
|
43
|
+
'With more items, resize the viewport to see them collapse one at a time rather than all at once.',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
args: {
|
|
48
|
+
items: [
|
|
49
|
+
{ label: 'Home', href: '/' },
|
|
50
|
+
{ label: 'Environmental land management', href: '/elm' },
|
|
51
|
+
{ label: 'Sustainable Farming Incentive', href: '/elm/sfi' },
|
|
52
|
+
{ label: 'Applications', href: '/elm/sfi/applications' },
|
|
53
|
+
{ label: 'Agreement holders', href: '/elm/sfi/applications/agreement-holders' },
|
|
54
|
+
{ label: 'Application ABC123' },
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const Inverse: Story = {
|
|
60
|
+
parameters: {
|
|
61
|
+
docs: {
|
|
62
|
+
description: {
|
|
63
|
+
story:
|
|
64
|
+
'Pass `appearance="inverse"` on a dark background, such as the accent-coloured Hero. Drives both the link colour and the current-page text/separator colour together, from one prop.',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
args: {
|
|
69
|
+
appearance: 'inverse',
|
|
70
|
+
items: [
|
|
71
|
+
{ label: 'Home', href: '/' },
|
|
72
|
+
{ label: 'Applications', href: '/applications' },
|
|
73
|
+
{ label: 'Current application' },
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
render: (args) => (
|
|
77
|
+
<div className="bg-accent p-gds-4">
|
|
78
|
+
<Breadcrumb {...args} />
|
|
79
|
+
</div>
|
|
80
|
+
),
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const TwoItems: Story = {
|
|
84
|
+
parameters: {
|
|
85
|
+
docs: {
|
|
86
|
+
description: {
|
|
87
|
+
story: 'With only two items there is nothing to collapse, so no ellipsis ever appears.',
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
args: {
|
|
92
|
+
items: [{ label: 'Home', href: '/' }, { label: 'Current page' }],
|
|
93
|
+
},
|
|
94
|
+
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import { LuChevronRight } from 'react-icons/lu';
|
|
4
|
+
|
|
5
|
+
import { cn } from '../../utils/components';
|
|
6
|
+
import { Link, type LinkAppearance } from '../Link/Link';
|
|
7
|
+
|
|
8
|
+
export type BreadcrumbItem = {
|
|
9
|
+
label: ReactNode;
|
|
10
|
+
href?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// Each middle item reveals at a progressively larger breakpoint the further
|
|
14
|
+
// it sits from the current page (the item right before it reveals first, at
|
|
15
|
+
// xs; the one before that at sm; and so on), so more of the trail appears
|
|
16
|
+
// as the screen grows rather than an all-or-nothing GDS-style cutoff.
|
|
17
|
+
// This project redefines the breakpoint scale entirely (see breakpoints.css,
|
|
18
|
+
// --breakpoint-*: initial then 2xs/xs/sm/md/lg only), there's no xl or 2xl
|
|
19
|
+
// here, those variants would silently compile to nothing.
|
|
20
|
+
// Written as complete, static class strings rather than built from a
|
|
21
|
+
// template, Tailwind can only pick up classes it finds literally in source.
|
|
22
|
+
const TIER_SEQUENCE = ['xs', 'sm', 'md', 'lg'] as const;
|
|
23
|
+
|
|
24
|
+
type Tier = (typeof TIER_SEQUENCE)[number];
|
|
25
|
+
|
|
26
|
+
const REVEAL_AT_TIER_CLASSES: Record<Tier, string> = {
|
|
27
|
+
xs: 'hidden xs:inline-flex',
|
|
28
|
+
sm: 'hidden sm:inline-flex',
|
|
29
|
+
md: 'hidden md:inline-flex',
|
|
30
|
+
lg: 'hidden lg:inline-flex',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Shown by default, hidden once every item it stands in for is visible.
|
|
34
|
+
const ELLIPSIS_TIER_CLASSES: Record<Tier, string> = {
|
|
35
|
+
xs: 'inline-flex xs:hidden',
|
|
36
|
+
sm: 'inline-flex sm:hidden',
|
|
37
|
+
md: 'inline-flex md:hidden',
|
|
38
|
+
lg: 'inline-flex lg:hidden',
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const tierForDepth = (depthFromEnd: number): Tier =>
|
|
42
|
+
TIER_SEQUENCE[Math.min(depthFromEnd - 1, TIER_SEQUENCE.length - 1)]!;
|
|
43
|
+
|
|
44
|
+
// Maps to Link's own appearances rather than inventing new ones: contrast
|
|
45
|
+
// (dark text) for a normal page background, inverse (white text) for a dark
|
|
46
|
+
// background like the Hero. data-appearance on the nav drives the matching
|
|
47
|
+
// colour for the current-page text and separator icons (see Breadcrumb.css),
|
|
48
|
+
// so both stay in sync with whichever one is picked here.
|
|
49
|
+
const BREADCRUMB_LINK_APPEARANCES = {
|
|
50
|
+
default: 'contrast',
|
|
51
|
+
inverse: 'inverse',
|
|
52
|
+
} as const satisfies Record<string, LinkAppearance>;
|
|
53
|
+
|
|
54
|
+
export type BreadcrumbAppearance = keyof typeof BREADCRUMB_LINK_APPEARANCES;
|
|
55
|
+
|
|
56
|
+
export type BreadcrumbProps = Omit<ComponentProps<'nav'>, 'children'> & {
|
|
57
|
+
items: BreadcrumbItem[];
|
|
58
|
+
appearance?: BreadcrumbAppearance;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const Breadcrumb = ({
|
|
62
|
+
items,
|
|
63
|
+
appearance = 'default',
|
|
64
|
+
className,
|
|
65
|
+
...props
|
|
66
|
+
}: BreadcrumbProps) => {
|
|
67
|
+
const total = items.length;
|
|
68
|
+
// The item right after Home (index 1) has the largest depth, so it's the
|
|
69
|
+
// last one revealed as breakpoints grow, once it's visible nothing is
|
|
70
|
+
// collapsed any more and the ellipsis itself should disappear.
|
|
71
|
+
const ellipsisTier = total > 2 ? tierForDepth(total - 2) : undefined;
|
|
72
|
+
|
|
73
|
+
const listItems = items.flatMap((item, index) => {
|
|
74
|
+
const isFirst = index === 0;
|
|
75
|
+
const isLast = index === total - 1;
|
|
76
|
+
const depthFromEnd = total - 1 - index;
|
|
77
|
+
const key = item.href ?? String(item.label);
|
|
78
|
+
|
|
79
|
+
const itemNode = (
|
|
80
|
+
<li
|
|
81
|
+
key={key}
|
|
82
|
+
data-slot="breadcrumb-item"
|
|
83
|
+
className={cn(
|
|
84
|
+
'cn-breadcrumb-item',
|
|
85
|
+
isFirst || isLast ? 'inline-flex' : REVEAL_AT_TIER_CLASSES[tierForDepth(depthFromEnd)],
|
|
86
|
+
)}
|
|
87
|
+
aria-current={isLast ? 'page' : undefined}
|
|
88
|
+
>
|
|
89
|
+
{!isFirst && (
|
|
90
|
+
<LuChevronRight aria-hidden strokeWidth={2.5} className="cn-breadcrumb-separator" />
|
|
91
|
+
)}
|
|
92
|
+
|
|
93
|
+
{item.href && !isLast ? (
|
|
94
|
+
<Link href={item.href} appearance={BREADCRUMB_LINK_APPEARANCES[appearance]}>
|
|
95
|
+
{item.label}
|
|
96
|
+
</Link>
|
|
97
|
+
) : (
|
|
98
|
+
<span className="cn-breadcrumb-page">{item.label}</span>
|
|
99
|
+
)}
|
|
100
|
+
</li>
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
if (isFirst && ellipsisTier) {
|
|
104
|
+
return [
|
|
105
|
+
itemNode,
|
|
106
|
+
<li
|
|
107
|
+
key="ellipsis"
|
|
108
|
+
aria-hidden
|
|
109
|
+
data-slot="breadcrumb-ellipsis"
|
|
110
|
+
className={cn('cn-breadcrumb-item', ELLIPSIS_TIER_CLASSES[ellipsisTier])}
|
|
111
|
+
>
|
|
112
|
+
<LuChevronRight aria-hidden strokeWidth={2.5} className="cn-breadcrumb-separator" />
|
|
113
|
+
|
|
114
|
+
<span className="cn-breadcrumb-ellipsis-text">…</span>
|
|
115
|
+
</li>,
|
|
116
|
+
];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return [itemNode];
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<nav
|
|
124
|
+
aria-label="Breadcrumb"
|
|
125
|
+
data-slot="breadcrumb"
|
|
126
|
+
data-appearance={appearance}
|
|
127
|
+
className={cn('cn-breadcrumb', className)}
|
|
128
|
+
{...props}
|
|
129
|
+
>
|
|
130
|
+
<ol data-slot="breadcrumb-list" className="cn-breadcrumb-list">
|
|
131
|
+
{listItems}
|
|
132
|
+
</ol>
|
|
133
|
+
</nav>
|
|
134
|
+
);
|
|
135
|
+
};
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/* MARK: Sizes */
|
|
2
|
+
|
|
3
|
+
@utility cn-button-size-sm {
|
|
4
|
+
&:not([data-variant='icon']) {
|
|
5
|
+
/* min-height target is 32px, minus whatever --cn-button-shadow-size the
|
|
6
|
+
appearance adds below the box (see MARK: Base button), so the total
|
|
7
|
+
visual footprint (box + shadow) always lands on 32px. */
|
|
8
|
+
@apply text-sm w-auto;
|
|
9
|
+
min-height: calc(2rem - var(--cn-button-shadow-size, 0px));
|
|
10
|
+
padding-block: calc(var(--spacing-gds-1) - var(--border-width-form));
|
|
11
|
+
padding-inline: var(--spacing-gds-2);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
&[data-variant='icon'] {
|
|
15
|
+
/* Width stays fixed (square). Only height gets the same shadow
|
|
16
|
+
compensation as the text sizes above, so the shadow can render while
|
|
17
|
+
the total footprint (box + shadow) stays a 32px square. */
|
|
18
|
+
@apply cn-icon-sm;
|
|
19
|
+
height: calc(2rem - var(--cn-button-shadow-size, 0px));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@utility cn-button-size-base {
|
|
24
|
+
&:not([data-variant='icon']) {
|
|
25
|
+
/* 40px target, matches the fixed 40px (h-10) height of form inputs like
|
|
26
|
+
Input/Select, so a base-size button in an input group aligns exactly. */
|
|
27
|
+
@apply text-base w-full sm:w-auto;
|
|
28
|
+
min-height: calc(2.5rem - var(--cn-button-shadow-size, 0px));
|
|
29
|
+
padding-block: calc(var(--spacing-gds-1) - var(--border-width-form));
|
|
30
|
+
padding-inline: var(--spacing-gds-2);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&[data-variant='icon'] {
|
|
34
|
+
@apply cn-icon-base;
|
|
35
|
+
height: calc(2.5rem - var(--cn-button-shadow-size, 0px));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@utility cn-button-size-lg {
|
|
40
|
+
&:not([data-variant='icon']) {
|
|
41
|
+
/* 48px target, same shadow-compensation as the other sizes. */
|
|
42
|
+
@apply text-lg sm:w-auto;
|
|
43
|
+
min-height: calc(3rem - var(--cn-button-shadow-size, 0px));
|
|
44
|
+
padding-block: calc(var(--spacing-gds-2) - var(--border-width-form));
|
|
45
|
+
padding-inline: var(--spacing-gds-3);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
&[data-variant='icon'] {
|
|
49
|
+
@apply cn-icon-lg;
|
|
50
|
+
height: calc(3rem - var(--cn-button-shadow-size, 0px));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* MARK: Icon variant
|
|
55
|
+
shrink-0: an icon button is meant to always render as a fixed square, but
|
|
56
|
+
cn-button's own base sets w-full, so without this, one sitting in a flex
|
|
57
|
+
row alongside other content (a header toolbar, an InputGroup suffix) would
|
|
58
|
+
shrink below its intended size once that row runs out of space, same as
|
|
59
|
+
any other flex-shrink: 1 default. */
|
|
60
|
+
@utility cn-button-variant-icon {
|
|
61
|
+
@apply shrink-0;
|
|
62
|
+
|
|
63
|
+
& svg {
|
|
64
|
+
@apply w-full h-full;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* MARK: Base button */
|
|
69
|
+
|
|
70
|
+
@utility cn-button {
|
|
71
|
+
@apply relative border-form border-solid border-transparent no-underline cursor-pointer w-full;
|
|
72
|
+
/* Generic so every appearance can share one declaration by setting the two
|
|
73
|
+
variables instead of repeating the box-shadow itself. --cn-button-shadow-size
|
|
74
|
+
also drives the height compensation in cn-button-size-*, so it should stay
|
|
75
|
+
constant across states. Use box-shadow: none directly (not the size
|
|
76
|
+
variable) to hide the bar for a given state, so height math never shifts. */
|
|
77
|
+
box-shadow: 0 var(--cn-button-shadow-size, 0px) 0 var(--cn-button-shadow-color, transparent);
|
|
78
|
+
|
|
79
|
+
/* Extend click target to cover the button's own border on all sides */
|
|
80
|
+
&::before {
|
|
81
|
+
@apply content-[''] block absolute bg-transparent;
|
|
82
|
+
top: calc(var(--border-width-form) * -1);
|
|
83
|
+
right: calc(var(--border-width-form) * -1);
|
|
84
|
+
bottom: calc(var(--border-width-form) * -1);
|
|
85
|
+
left: calc(var(--border-width-form) * -1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Active: shift button down and clear the bottom shadow to simulate pressing */
|
|
89
|
+
&:active:not(:disabled) {
|
|
90
|
+
transform: translateY(var(--border-width-form));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
&:active:not(:disabled):not(:focus) {
|
|
94
|
+
box-shadow: none;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
&:active:not(:disabled):focus {
|
|
98
|
+
box-shadow: inset 0 0 0 1px var(--color-focus);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Focus: yellow border + inset yellow ring. Inset is fine here, the
|
|
102
|
+
border itself is coloured (not transparent) during focus, so there's no
|
|
103
|
+
gap for the ring to float over. */
|
|
104
|
+
&:focus {
|
|
105
|
+
@apply border-focus;
|
|
106
|
+
box-shadow: inset 0 0 0 1px var(--color-focus);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Focus when not hovered or active: full yellow highlight (GDS pattern).
|
|
110
|
+
Uses the same --cn-button-shadow-size as the resting appearance shadow
|
|
111
|
+
below, so it renders (or doesn't) exactly like the appearance's own bar. */
|
|
112
|
+
&:focus:not(:active):not(:hover) {
|
|
113
|
+
@apply bg-focus text-on-focus border-focus;
|
|
114
|
+
box-shadow: 0 var(--cn-button-shadow-size, 0px) 0 var(--color-on-focus);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
&:disabled {
|
|
118
|
+
@apply opacity-50;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* MARK: Appearances */
|
|
123
|
+
|
|
124
|
+
/* The bottom "shadow" bar is a flush, non-inset box-shadow, not a
|
|
125
|
+
border-bottom-color. Colouring only one side of an otherwise-transparent
|
|
126
|
+
border renders a diagonal miter at the corners (adjacent border edges of
|
|
127
|
+
different colours always blend diagonally where they meet). A non-inset
|
|
128
|
+
box-shadow has no adjacent edge to miter against, and unlike an inset
|
|
129
|
+
shadow, it starts flush against the border-box edge instead of being
|
|
130
|
+
painted behind the transparent border and looking detached or floating.
|
|
131
|
+
It does overflow past the border-box, so each shadow-bearing appearance
|
|
132
|
+
sets --cn-button-shadow-size, which cn-button-size-* subtracts back out of
|
|
133
|
+
min-height (or, for the icon variant, height). The total visual footprint
|
|
134
|
+
(box + shadow) always lands on the same size as a sibling form input, and
|
|
135
|
+
icon buttons stay square because only their height is compensated, not
|
|
136
|
+
their width. Appearances that don't set the variable (ghost, panel) get
|
|
137
|
+
0px via the fallback, so no shadow and no compensation. Colour is a
|
|
138
|
+
separate variable from size so cn-button-link can restore just the colour
|
|
139
|
+
on active without disturbing the height compensation. */
|
|
140
|
+
|
|
141
|
+
@utility cn-button-appearance-primary {
|
|
142
|
+
@apply bg-accent text-on-accent;
|
|
143
|
+
--cn-button-shadow-size: var(--border-width-form);
|
|
144
|
+
--cn-button-shadow-color: var(--color-accent-shadow);
|
|
145
|
+
|
|
146
|
+
&:hover:not(:disabled) {
|
|
147
|
+
@apply bg-accent-hover;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@utility cn-button-appearance-secondary {
|
|
152
|
+
@apply bg-wash text-body;
|
|
153
|
+
--cn-button-shadow-size: var(--border-width-form);
|
|
154
|
+
--cn-button-shadow-color: var(--color-neutral-mid);
|
|
155
|
+
|
|
156
|
+
&:hover:not(:disabled) {
|
|
157
|
+
@apply bg-muted;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@utility cn-button-appearance-destructive {
|
|
162
|
+
@apply bg-error text-on-error;
|
|
163
|
+
--cn-button-shadow-size: var(--border-width-form);
|
|
164
|
+
--cn-button-shadow-color: var(--color-error-shadow);
|
|
165
|
+
|
|
166
|
+
&:hover:not(:disabled) {
|
|
167
|
+
@apply bg-error-hover;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@utility cn-button-appearance-inverse {
|
|
172
|
+
@apply bg-wash text-accent-safe;
|
|
173
|
+
--cn-button-shadow-size: var(--border-width-form);
|
|
174
|
+
--cn-button-shadow-color: var(--color-neutral-mid);
|
|
175
|
+
|
|
176
|
+
&:hover:not(:disabled) {
|
|
177
|
+
@apply bg-surface-hover;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@utility cn-button-appearance-ghost {
|
|
182
|
+
@apply bg-transparent text-body;
|
|
183
|
+
|
|
184
|
+
&:hover:not(:disabled) {
|
|
185
|
+
@apply bg-transparent;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
&:focus:not(:active):not(:hover) {
|
|
189
|
+
@apply shadow-none;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* Ghost has no bottom border to press into, so no shift or border clear */
|
|
193
|
+
&:active:not(:disabled) {
|
|
194
|
+
@apply bg-black/5 transform-none;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
@utility cn-button-appearance-panel {
|
|
199
|
+
@apply panel text-body;
|
|
200
|
+
|
|
201
|
+
&:focus:not(:active):not(:hover) {
|
|
202
|
+
@apply shadow-none;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* bg-black/5 (ghost's treatment, copied here originally) is a
|
|
206
|
+
semi-transparent overlay, fine over ghost's own transparent background,
|
|
207
|
+
but here it replaces panel's opaque bg-panel outright rather than
|
|
208
|
+
layering on top of it, so the button looks like it's gone transparent
|
|
209
|
+
instead of staying solid and going slightly darker. bg-muted is a real
|
|
210
|
+
solid colour, one step down the same neutral scale panel's white sits
|
|
211
|
+
on top of. */
|
|
212
|
+
&:active:not(:disabled) {
|
|
213
|
+
@apply bg-muted transform-none;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/* MARK: Variants */
|
|
218
|
+
|
|
219
|
+
@utility cn-button-variant-cta {
|
|
220
|
+
@apply font-bold;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/* MARK: Skeleton
|
|
224
|
+
min-height on cn-button-size-* already guarantees the outer box matches a
|
|
225
|
+
real button regardless of content, so this bar just needs to look
|
|
226
|
+
reasonable inside it, not hit an exact height. */
|
|
227
|
+
@utility cn-button-skeleton-bar {
|
|
228
|
+
@apply h-[0.6em] w-16;
|
|
229
|
+
}
|
|
@@ -1,38 +1,158 @@
|
|
|
1
|
+
import { LuCopy } from 'react-icons/lu';
|
|
1
2
|
import { action } from 'storybook/actions';
|
|
2
3
|
|
|
3
4
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
5
|
|
|
5
6
|
import { Button } from './Button';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
const meta: Meta<typeof Button> = {
|
|
9
|
+
title: 'Components/Button/Button',
|
|
9
10
|
component: Button,
|
|
10
|
-
|
|
11
|
+
tags: ['autodocs'],
|
|
12
|
+
parameters: {
|
|
13
|
+
docs: {
|
|
14
|
+
description: {
|
|
15
|
+
component:
|
|
16
|
+
'Use the button component to help users carry out an action like starting an application or saving their information.',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
argTypes: {
|
|
21
|
+
appearance: {
|
|
22
|
+
control: { type: 'radio' },
|
|
23
|
+
options: ['primary', 'secondary', 'destructive', 'inverse', 'ghost', 'panel'],
|
|
24
|
+
},
|
|
25
|
+
variant: {
|
|
26
|
+
control: { type: 'radio' },
|
|
27
|
+
options: ['default', 'cta', 'icon'],
|
|
28
|
+
},
|
|
29
|
+
size: {
|
|
30
|
+
control: { type: 'radio' },
|
|
31
|
+
options: ['base', 'sm', 'lg'],
|
|
32
|
+
},
|
|
33
|
+
onClick: { action: 'onClick' },
|
|
34
|
+
asChild: { control: 'boolean' },
|
|
35
|
+
children: { control: 'text' },
|
|
36
|
+
},
|
|
37
|
+
args: {
|
|
38
|
+
appearance: 'primary',
|
|
39
|
+
size: 'base',
|
|
40
|
+
children: 'Button',
|
|
41
|
+
onClick: action('onClick'),
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default meta;
|
|
46
|
+
|
|
47
|
+
type Story = StoryObj<typeof Button>;
|
|
48
|
+
|
|
49
|
+
export const Primary: Story = {
|
|
50
|
+
args: {
|
|
51
|
+
appearance: 'primary',
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const Secondary: Story = {
|
|
56
|
+
args: {
|
|
57
|
+
appearance: 'secondary',
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const Destructive: Story = {
|
|
62
|
+
args: {
|
|
63
|
+
appearance: 'destructive',
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const Inverse: Story = {
|
|
68
|
+
args: {
|
|
69
|
+
appearance: 'inverse',
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const Ghost: Story = {
|
|
74
|
+
args: {
|
|
75
|
+
appearance: 'ghost',
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const Panel: Story = {
|
|
80
|
+
args: {
|
|
81
|
+
appearance: 'panel',
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const IconButton: Story = {
|
|
86
|
+
args: {
|
|
87
|
+
variant: 'icon',
|
|
88
|
+
children: <LuCopy />,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const Sizes: Story = {
|
|
93
|
+
render: (args) => (
|
|
94
|
+
<div className="flex items-center gap-3">
|
|
95
|
+
<Button {...args} size="sm">
|
|
96
|
+
SM
|
|
97
|
+
</Button>
|
|
98
|
+
|
|
99
|
+
<Button {...args} size="base">
|
|
100
|
+
Default
|
|
101
|
+
</Button>
|
|
11
102
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
103
|
+
<Button {...args} size="lg">
|
|
104
|
+
LG
|
|
105
|
+
</Button>
|
|
106
|
+
</div>
|
|
107
|
+
),
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export const ClickToAction: Story = {
|
|
111
|
+
render: (args) => (
|
|
112
|
+
<div className="flex flex-col gap-3">
|
|
113
|
+
<div className="flex items-center gap-3">
|
|
114
|
+
<Button {...args} appearance="primary" variant="cta">
|
|
115
|
+
Primary CTA
|
|
18
116
|
</Button>
|
|
19
|
-
</div>
|
|
20
117
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
Secondary
|
|
118
|
+
<Button {...args} appearance="secondary" variant="cta">
|
|
119
|
+
Secondary CTA
|
|
24
120
|
</Button>
|
|
25
|
-
</div>
|
|
26
121
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
Inverse
|
|
122
|
+
<Button {...args} appearance="inverse" variant="cta">
|
|
123
|
+
Inverse CTA
|
|
30
124
|
</Button>
|
|
31
125
|
</div>
|
|
126
|
+
</div>
|
|
127
|
+
),
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export const Disabled: Story = {
|
|
131
|
+
render: (args) => (
|
|
132
|
+
<div className="flex flex-col gap-3">
|
|
133
|
+
<div className="flex items-center gap-3">
|
|
134
|
+
<Button {...args} appearance="primary" disabled>
|
|
135
|
+
Primary Disabled
|
|
136
|
+
</Button>
|
|
137
|
+
|
|
138
|
+
<Button {...args} appearance="secondary" disabled>
|
|
139
|
+
Secondary Disabled
|
|
140
|
+
</Button>
|
|
141
|
+
|
|
142
|
+
<Button {...args} appearance="destructive" disabled>
|
|
143
|
+
Danger Disabled
|
|
144
|
+
</Button>
|
|
145
|
+
|
|
146
|
+
<Button {...args} appearance="inverse" disabled>
|
|
147
|
+
Inverse Disabled
|
|
148
|
+
</Button>
|
|
149
|
+
|
|
150
|
+
<Button {...args} appearance="ghost" disabled>
|
|
151
|
+
Ghost Disabled
|
|
152
|
+
</Button>
|
|
32
153
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
Disabled Button
|
|
154
|
+
<Button {...args} appearance="panel" disabled>
|
|
155
|
+
Panel Disabled
|
|
36
156
|
</Button>
|
|
37
157
|
</div>
|
|
38
158
|
</div>
|