@tpzdsp/next-toolkit 2.5.1 → 3.1.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 +21 -12
- 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 +34 -0
- package/src/components/ErrorModal/ErrorModal.stories.tsx +100 -0
- package/src/components/ErrorModal/ErrorModal.tsx +123 -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 +3 -2
- package/src/components/Footer/Footer.stories.tsx +27 -0
- package/src/components/Footer/Footer.tsx +46 -0
- package/src/components/Footer/Licence.tsx +18 -0
- package/src/components/Footer/MetaLinks.tsx +47 -0
- package/src/components/Footer/Small/SmallFooter.stories.tsx +3 -0
- package/src/components/Footer/Small/SmallFooter.tsx +53 -41
- 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 +304 -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 +111 -0
- package/src/components/Modal/Modal.stories.tsx +94 -155
- package/src/components/Modal/Modal.tsx +141 -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 +202 -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 +296 -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 +343 -61
- package/src/errors/errorDisplay.ts +70 -0
- package/src/errors/index.ts +1 -0
- package/src/http/constants.ts +2 -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/footer/MetaLinks.tsx +0 -36
- 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
|
@@ -1,43 +1,68 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { cn } from '../../utils';
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
import { Slot } from 'radix-ui';
|
|
4
|
+
|
|
5
|
+
import { cn } from '../../utils/components';
|
|
6
|
+
|
|
7
|
+
const BUTTON_APPEARANCES = {
|
|
8
|
+
primary: 'cn-button-appearance-primary',
|
|
9
|
+
secondary: 'cn-button-appearance-secondary',
|
|
10
|
+
destructive: 'cn-button-appearance-destructive',
|
|
11
|
+
inverse: 'cn-button-appearance-inverse',
|
|
12
|
+
ghost: 'cn-button-appearance-ghost',
|
|
13
|
+
panel: 'cn-button-appearance-panel',
|
|
14
|
+
} as const;
|
|
15
|
+
|
|
16
|
+
const BUTTON_VARIANTS = {
|
|
17
|
+
default: 'cn-button-variant-default',
|
|
18
|
+
cta: 'cn-button-variant-cta',
|
|
19
|
+
icon: 'cn-button-variant-icon',
|
|
20
|
+
} as const;
|
|
9
21
|
|
|
10
|
-
|
|
22
|
+
const BUTTON_SIZES = {
|
|
23
|
+
base: 'cn-button-size-base',
|
|
24
|
+
sm: 'cn-button-size-sm',
|
|
25
|
+
lg: 'cn-button-size-lg',
|
|
26
|
+
} as const;
|
|
11
27
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
28
|
+
export type ButtonAppearance = keyof typeof BUTTON_APPEARANCES;
|
|
29
|
+
export type ButtonVariant = keyof typeof BUTTON_VARIANTS;
|
|
30
|
+
export type ButtonSize = keyof typeof BUTTON_SIZES;
|
|
31
|
+
|
|
32
|
+
export type ButtonProps = ComponentProps<'button'> & {
|
|
33
|
+
asChild?: boolean;
|
|
34
|
+
appearance?: ButtonAppearance;
|
|
35
|
+
variant?: ButtonVariant;
|
|
36
|
+
size?: ButtonSize;
|
|
16
37
|
};
|
|
17
38
|
|
|
18
|
-
// NOTE: some of the styles are applied in `tailwind.css`, under `Button Styles`
|
|
19
39
|
export const Button = ({
|
|
20
|
-
type = 'button',
|
|
21
|
-
variant = 'primary',
|
|
22
40
|
className,
|
|
23
|
-
|
|
41
|
+
appearance = 'primary',
|
|
42
|
+
variant = 'default',
|
|
43
|
+
size = 'base',
|
|
44
|
+
asChild = false,
|
|
24
45
|
...props
|
|
25
46
|
}: ButtonProps) => {
|
|
47
|
+
const Comp = asChild ? Slot.Root : 'button';
|
|
48
|
+
|
|
26
49
|
return (
|
|
27
|
-
<
|
|
28
|
-
|
|
50
|
+
<Comp
|
|
51
|
+
{...props}
|
|
52
|
+
data-slot="button"
|
|
53
|
+
data-appearance={appearance}
|
|
54
|
+
data-variant={variant}
|
|
55
|
+
data-size={size}
|
|
29
56
|
className={cn(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
57
|
+
'cn-button group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap',
|
|
58
|
+
'outline-none select-none disabled:cursor-not-allowed',
|
|
59
|
+
'[&_svg]:pointer-events-none [&_svg]:shrink-0',
|
|
60
|
+
BUTTON_APPEARANCES[appearance],
|
|
61
|
+
BUTTON_VARIANTS[variant],
|
|
62
|
+
BUTTON_SIZES[size],
|
|
36
63
|
className,
|
|
37
64
|
)}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
{children}
|
|
41
|
-
</button>
|
|
65
|
+
role="button"
|
|
66
|
+
/>
|
|
42
67
|
);
|
|
43
68
|
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
import { ButtonSkeleton } from './ButtonSkeleton';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof ButtonSkeleton> = {
|
|
6
|
+
title: 'Components/Button/Skeleton',
|
|
7
|
+
component: ButtonSkeleton,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component:
|
|
13
|
+
"Placeholder for a Button while whatever decides its label or visibility is loading. Renders a real, disabled Button with the same appearance/variant/size props, so it always matches the real button's dimensions exactly, no layout shift when it swaps in.",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
argTypes: {
|
|
18
|
+
appearance: {
|
|
19
|
+
control: { type: 'select' },
|
|
20
|
+
options: ['primary', 'secondary', 'destructive', 'inverse', 'ghost', 'panel'],
|
|
21
|
+
},
|
|
22
|
+
size: {
|
|
23
|
+
control: { type: 'radio' },
|
|
24
|
+
options: ['sm', 'base', 'lg'],
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default meta;
|
|
30
|
+
|
|
31
|
+
type Story = StoryObj<typeof ButtonSkeleton>;
|
|
32
|
+
|
|
33
|
+
export const Default: Story = {
|
|
34
|
+
args: {
|
|
35
|
+
appearance: 'primary',
|
|
36
|
+
size: 'base',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const Sizes: Story = {
|
|
41
|
+
render: () => (
|
|
42
|
+
<div className="flex items-center gap-gds-2">
|
|
43
|
+
<ButtonSkeleton size="sm" />
|
|
44
|
+
|
|
45
|
+
<ButtonSkeleton size="base" />
|
|
46
|
+
|
|
47
|
+
<ButtonSkeleton size="lg" />
|
|
48
|
+
</div>
|
|
49
|
+
),
|
|
50
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
|
|
3
|
+
import { Button } from './Button';
|
|
4
|
+
import { Skeleton } from '../Skeleton/Skeleton';
|
|
5
|
+
|
|
6
|
+
export type ButtonSkeletonProps = Omit<ComponentProps<typeof Button>, 'children' | 'disabled'> & {
|
|
7
|
+
children?: never;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const ButtonSkeleton = ({ className, ...props }: ButtonSkeletonProps) => (
|
|
11
|
+
<Button {...props} aria-hidden disabled tabIndex={-1} className={className}>
|
|
12
|
+
<Skeleton className="cn-button-skeleton-bar" />
|
|
13
|
+
</Button>
|
|
14
|
+
);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
@layer components {
|
|
2
|
+
/* MARK: ButtonGroup
|
|
3
|
+
GDS action group: flex-wrap with center alignment so all button types
|
|
4
|
+
(text, icon, link) sit on the same axis. Buttons handle their own mobile
|
|
5
|
+
full-width behaviour (w-full sm:w-auto), so the group itself stays flex. */
|
|
6
|
+
|
|
7
|
+
.cn-button-group {
|
|
8
|
+
@apply flex flex-wrap items-center gap-gds-2;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.cn-button-group[data-orientation='vertical'] {
|
|
12
|
+
@apply flex-col items-start;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* MARK: Compressed
|
|
16
|
+
Removes gap and shares the panel border between adjacent buttons by
|
|
17
|
+
collapsing one border-width of margin. Intended for icon button toolbars
|
|
18
|
+
using appearance="panel". Focused buttons raise above siblings via z-index
|
|
19
|
+
so the inset focus ring is never clipped by a neighbour. */
|
|
20
|
+
.cn-button-group[data-compressed] {
|
|
21
|
+
gap: 0;
|
|
22
|
+
|
|
23
|
+
& > * {
|
|
24
|
+
@apply relative;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
& > * + * {
|
|
28
|
+
margin-left: calc(var(--border-width-form) * -1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&[data-orientation='vertical'] > * + * {
|
|
32
|
+
margin-left: 0;
|
|
33
|
+
margin-top: calc(var(--border-width-form) * -1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
& > *:focus-within {
|
|
37
|
+
z-index: 1;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* MARK: Text */
|
|
42
|
+
|
|
43
|
+
.cn-button-group-text {
|
|
44
|
+
@apply flex items-center text-base;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* MARK: Separator */
|
|
48
|
+
|
|
49
|
+
.cn-button-group-separator {
|
|
50
|
+
@apply self-stretch;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { LuMaximize2, LuMinus, LuPlus } from 'react-icons/lu';
|
|
2
|
+
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
|
+
|
|
5
|
+
import { ButtonGroup, ButtonGroupSeparator, ButtonGroupText } from './ButtonGroup';
|
|
6
|
+
import { Button } from '../Button/Button';
|
|
7
|
+
import { LinkButton } from '../LinkButton/LinkButton';
|
|
8
|
+
|
|
9
|
+
const meta: Meta<typeof ButtonGroup> = {
|
|
10
|
+
title: 'Components/ButtonGroup',
|
|
11
|
+
component: ButtonGroup,
|
|
12
|
+
tags: ['autodocs'],
|
|
13
|
+
parameters: {
|
|
14
|
+
docs: {
|
|
15
|
+
description: {
|
|
16
|
+
component:
|
|
17
|
+
'Groups related action buttons with consistent GDS-aligned spacing. Use for form submission areas where a primary action is accompanied by a secondary button or cancel link.',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
argTypes: {
|
|
22
|
+
orientation: {
|
|
23
|
+
control: { type: 'radio' },
|
|
24
|
+
options: ['horizontal', 'vertical'],
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
args: {
|
|
28
|
+
orientation: 'horizontal',
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default meta;
|
|
33
|
+
|
|
34
|
+
type Story = StoryObj<typeof ButtonGroup>;
|
|
35
|
+
|
|
36
|
+
export const PrimaryWithCancel: Story = {
|
|
37
|
+
render: (args) => (
|
|
38
|
+
<ButtonGroup {...args}>
|
|
39
|
+
<Button appearance="primary">Save and continue</Button>
|
|
40
|
+
|
|
41
|
+
<LinkButton href="/">Cancel</LinkButton>
|
|
42
|
+
</ButtonGroup>
|
|
43
|
+
),
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const PrimaryAndSecondary: Story = {
|
|
47
|
+
render: (args) => (
|
|
48
|
+
<ButtonGroup {...args}>
|
|
49
|
+
<Button appearance="primary">Save and continue</Button>
|
|
50
|
+
|
|
51
|
+
<Button appearance="secondary">Save as draft</Button>
|
|
52
|
+
</ButtonGroup>
|
|
53
|
+
),
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const WithText: Story = {
|
|
57
|
+
render: (args) => (
|
|
58
|
+
<ButtonGroup {...args}>
|
|
59
|
+
<Button appearance="primary">Accept all</Button>
|
|
60
|
+
|
|
61
|
+
<ButtonGroupText>or</ButtonGroupText>
|
|
62
|
+
|
|
63
|
+
<LinkButton href="/">Manage preferences</LinkButton>
|
|
64
|
+
</ButtonGroup>
|
|
65
|
+
),
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const Vertical: Story = {
|
|
69
|
+
args: {
|
|
70
|
+
orientation: 'vertical',
|
|
71
|
+
},
|
|
72
|
+
render: (args) => (
|
|
73
|
+
<ButtonGroup {...args}>
|
|
74
|
+
<Button appearance="primary">Save and continue</Button>
|
|
75
|
+
|
|
76
|
+
<Button appearance="secondary">Save as draft</Button>
|
|
77
|
+
|
|
78
|
+
<LinkButton href="/">Cancel</LinkButton>
|
|
79
|
+
</ButtonGroup>
|
|
80
|
+
),
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const WithSeparator: Story = {
|
|
84
|
+
render: (args) => (
|
|
85
|
+
<ButtonGroup {...args}>
|
|
86
|
+
<Button appearance="primary">Save and continue</Button>
|
|
87
|
+
|
|
88
|
+
<Button appearance="secondary">Save as draft</Button>
|
|
89
|
+
|
|
90
|
+
<ButtonGroupSeparator />
|
|
91
|
+
|
|
92
|
+
<Button appearance="destructive">Delete</Button>
|
|
93
|
+
</ButtonGroup>
|
|
94
|
+
),
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export const DestructiveGroup: Story = {
|
|
98
|
+
render: (args) => (
|
|
99
|
+
<ButtonGroup {...args}>
|
|
100
|
+
<Button appearance="destructive">Delete account</Button>
|
|
101
|
+
|
|
102
|
+
<LinkButton href="/">Cancel</LinkButton>
|
|
103
|
+
</ButtonGroup>
|
|
104
|
+
),
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export const CompressedHorizontal: Story = {
|
|
108
|
+
parameters: {
|
|
109
|
+
docs: {
|
|
110
|
+
description: {
|
|
111
|
+
story:
|
|
112
|
+
'Compressed removes the gap and shares borders between adjacent panel buttons. Use for map toolbars and icon button clusters.',
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
render: () => (
|
|
117
|
+
<ButtonGroup compressed>
|
|
118
|
+
<Button variant="icon" appearance="panel" aria-label="Zoom in">
|
|
119
|
+
<LuPlus aria-hidden />
|
|
120
|
+
</Button>
|
|
121
|
+
|
|
122
|
+
<Button variant="icon" appearance="panel" aria-label="Zoom out">
|
|
123
|
+
<LuMinus aria-hidden />
|
|
124
|
+
</Button>
|
|
125
|
+
|
|
126
|
+
<Button variant="icon" appearance="panel" aria-label="Full screen">
|
|
127
|
+
<LuMaximize2 aria-hidden />
|
|
128
|
+
</Button>
|
|
129
|
+
</ButtonGroup>
|
|
130
|
+
),
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export const CompressedVertical: Story = {
|
|
134
|
+
parameters: {
|
|
135
|
+
docs: {
|
|
136
|
+
description: {
|
|
137
|
+
story: 'Compressed vertical — the default layout for map control toolbars.',
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
render: () => (
|
|
142
|
+
<ButtonGroup orientation="vertical" compressed role="toolbar" aria-label="Map controls">
|
|
143
|
+
<Button variant="icon" appearance="panel" aria-label="Full screen">
|
|
144
|
+
<LuMaximize2 aria-hidden />
|
|
145
|
+
</Button>
|
|
146
|
+
|
|
147
|
+
<Button variant="icon" appearance="panel" aria-label="Zoom in">
|
|
148
|
+
<LuPlus aria-hidden />
|
|
149
|
+
</Button>
|
|
150
|
+
|
|
151
|
+
<Button variant="icon" appearance="panel" aria-label="Zoom out">
|
|
152
|
+
<LuMinus aria-hidden />
|
|
153
|
+
</Button>
|
|
154
|
+
</ButtonGroup>
|
|
155
|
+
),
|
|
156
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
|
|
3
|
+
import { Slot } from 'radix-ui';
|
|
4
|
+
|
|
5
|
+
import { cn } from '../../utils/components';
|
|
6
|
+
import { Paragraph } from '../Paragraph/Paragraph';
|
|
7
|
+
import { Separator } from '../Separator/Separator';
|
|
8
|
+
|
|
9
|
+
export type ButtonGroupOrientation = 'horizontal' | 'vertical';
|
|
10
|
+
|
|
11
|
+
export type ButtonGroupProps = ComponentProps<'div'> & {
|
|
12
|
+
orientation?: ButtonGroupOrientation;
|
|
13
|
+
compressed?: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const ButtonGroup = ({
|
|
17
|
+
className,
|
|
18
|
+
orientation = 'horizontal',
|
|
19
|
+
compressed = false,
|
|
20
|
+
...props
|
|
21
|
+
}: ButtonGroupProps) => (
|
|
22
|
+
<div
|
|
23
|
+
role="group"
|
|
24
|
+
data-slot="button-group"
|
|
25
|
+
data-orientation={orientation}
|
|
26
|
+
data-compressed={compressed || undefined}
|
|
27
|
+
className={cn('cn-button-group', className)}
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
export type ButtonGroupTextProps = ComponentProps<typeof Paragraph> & {
|
|
33
|
+
asChild?: boolean;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const ButtonGroupText = ({ className, asChild = false, ...props }: ButtonGroupTextProps) => {
|
|
37
|
+
const Comp = asChild ? Slot.Root : Paragraph;
|
|
38
|
+
|
|
39
|
+
return <Comp className={cn('cn-button-group-text', className)} {...props} />;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type ButtonGroupSeparatorProps = ComponentProps<typeof Separator>;
|
|
43
|
+
|
|
44
|
+
export const ButtonGroupSeparator = ({ className, ...props }: ButtonGroupSeparatorProps) => (
|
|
45
|
+
<Separator
|
|
46
|
+
data-slot="button-group-separator"
|
|
47
|
+
className={cn('cn-button-group-separator', className)}
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
);
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/* MARK: Base button-link
|
|
2
|
+
A button styled like a link. This *should not* be used for navigation, use
|
|
3
|
+
a real link instead. Use this for actions that are visually inline with text,
|
|
4
|
+
or anywhere a button needs link appearance without navigating.
|
|
5
|
+
|
|
6
|
+
Defined as @utility so it sits in the same cascade layer as cn-button and
|
|
7
|
+
can override its width/padding without needing !important. */
|
|
8
|
+
|
|
9
|
+
@utility cn-button-link {
|
|
10
|
+
@apply cn-link-decoration bg-transparent border-none p-0 w-fit;
|
|
11
|
+
box-shadow: none;
|
|
12
|
+
|
|
13
|
+
/* cn-button adds a ::before that extends the click target for the box-shadow.
|
|
14
|
+
ButtonLink has no shadow, so this just creates unexpected extra space. */
|
|
15
|
+
&::before {
|
|
16
|
+
display: none;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
&:hover:not(:disabled) {
|
|
20
|
+
text-decoration-thickness: max(3px, 0.1875rem, 0.12em);
|
|
21
|
+
text-decoration-skip-ink: none;
|
|
22
|
+
text-decoration-skip: none;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* No press shift so no depth shadow to consume */
|
|
26
|
+
&:active:not(:disabled) {
|
|
27
|
+
@apply top-0 transform-none;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Override base button focus in favour of GDS link focus box */
|
|
31
|
+
&:focus {
|
|
32
|
+
@apply text-on-focus bg-focus no-underline;
|
|
33
|
+
box-shadow:
|
|
34
|
+
0 -2px var(--color-focus),
|
|
35
|
+
0 4px var(--color-on-focus);
|
|
36
|
+
outline: 3px solid transparent;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Override base button yellow-bg focus state */
|
|
40
|
+
&:focus:not(:active):not(:hover) {
|
|
41
|
+
@apply bg-focus text-on-focus no-underline;
|
|
42
|
+
box-shadow:
|
|
43
|
+
0 -2px var(--color-focus),
|
|
44
|
+
0 4px var(--color-on-focus);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
&:disabled {
|
|
48
|
+
@apply opacity-50;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* MARK: Sizes
|
|
53
|
+
Adapt button sizes for link context: preserve text scale and touch-target
|
|
54
|
+
height but reset width and padding. */
|
|
55
|
+
|
|
56
|
+
@utility cn-button-link-size-sm {
|
|
57
|
+
&:not([data-variant='icon']) {
|
|
58
|
+
@apply cn-button-size-sm p-0 w-auto;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
&[data-variant='icon'] {
|
|
62
|
+
@apply cn-icon-sm;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@utility cn-button-link-size-base {
|
|
67
|
+
&:not([data-variant='icon']) {
|
|
68
|
+
@apply cn-button-size-base p-0 w-auto;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
&[data-variant='icon'] {
|
|
72
|
+
@apply cn-icon-base;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@utility cn-button-link-size-lg {
|
|
77
|
+
&:not([data-variant='icon']) {
|
|
78
|
+
@apply cn-button-size-lg p-0 w-auto;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
&[data-variant='icon'] {
|
|
82
|
+
@apply cn-icon-lg;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@layer components {
|
|
87
|
+
/* MARK: Appearances
|
|
88
|
+
Thin wrappers over the link appearance utilities. Keeps a stable
|
|
89
|
+
cn-button-link-* namespace so button-link-specific overrides can be added
|
|
90
|
+
here without touching the shared link utilities. */
|
|
91
|
+
|
|
92
|
+
.cn-button-link-appearance-primary {
|
|
93
|
+
@apply cn-link-appearance-primary;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.cn-button-link-appearance-inverse {
|
|
97
|
+
@apply cn-link-appearance-inverse;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.cn-button-link-appearance-contrast {
|
|
101
|
+
@apply cn-link-appearance-contrast;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* MARK: Variants */
|
|
105
|
+
|
|
106
|
+
/* Icon, square with svg filling the content area minus padding */
|
|
107
|
+
.cn-button-link-variant-icon {
|
|
108
|
+
@apply no-underline;
|
|
109
|
+
|
|
110
|
+
& svg {
|
|
111
|
+
@apply w-full h-full;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -1,72 +1,59 @@
|
|
|
1
|
+
import { LuExternalLink } from 'react-icons/lu';
|
|
2
|
+
|
|
1
3
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
4
|
|
|
3
5
|
import { ButtonLink } from './ButtonLink';
|
|
4
6
|
|
|
5
|
-
const meta = {
|
|
7
|
+
const meta: Meta<typeof ButtonLink> = {
|
|
6
8
|
title: 'Components/ButtonLink',
|
|
7
9
|
component: ButtonLink,
|
|
10
|
+
tags: ['autodocs'],
|
|
8
11
|
parameters: {
|
|
9
|
-
|
|
12
|
+
docs: {
|
|
13
|
+
description: {
|
|
14
|
+
component: 'Use ButtonLink to render a link-like button.',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
10
17
|
},
|
|
11
|
-
tags: ['autodocs'],
|
|
12
18
|
argTypes: {
|
|
13
|
-
|
|
14
|
-
control: '
|
|
15
|
-
options: ['
|
|
19
|
+
size: {
|
|
20
|
+
control: { type: 'radio' },
|
|
21
|
+
options: ['base', 'sm', 'lg'],
|
|
16
22
|
},
|
|
23
|
+
asChild: { control: 'boolean' },
|
|
24
|
+
onClick: { action: 'onClick' },
|
|
25
|
+
children: { control: 'text' },
|
|
17
26
|
},
|
|
18
|
-
} satisfies Meta<typeof ButtonLink>;
|
|
19
|
-
|
|
20
|
-
export default meta;
|
|
21
|
-
type Story = StoryObj<typeof meta>;
|
|
22
|
-
|
|
23
|
-
export const Default: Story = {
|
|
24
27
|
args: {
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
size: 'base',
|
|
29
|
+
children: 'Button link',
|
|
27
30
|
},
|
|
28
31
|
};
|
|
29
32
|
|
|
30
|
-
export
|
|
31
|
-
args: {
|
|
32
|
-
children: 'Show alert',
|
|
33
|
-
onClick: () => alert('Button clicked!'),
|
|
34
|
-
},
|
|
35
|
-
};
|
|
33
|
+
export default meta;
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
args: {
|
|
39
|
-
children: 'Submit form',
|
|
40
|
-
type: 'submit',
|
|
41
|
-
},
|
|
42
|
-
render: (args) => (
|
|
43
|
-
<form
|
|
44
|
-
onSubmit={(e) => {
|
|
45
|
-
e.preventDefault();
|
|
46
|
-
alert('Form submitted!');
|
|
47
|
-
}}
|
|
48
|
-
>
|
|
49
|
-
<ButtonLink {...args} />
|
|
50
|
-
</form>
|
|
51
|
-
),
|
|
52
|
-
};
|
|
35
|
+
type Story = StoryObj<typeof ButtonLink>;
|
|
53
36
|
|
|
54
|
-
export const
|
|
55
|
-
args: {
|
|
56
|
-
children: 'Disabled button link',
|
|
57
|
-
disabled: true,
|
|
58
|
-
},
|
|
59
|
-
};
|
|
37
|
+
export const Default: Story = {};
|
|
60
38
|
|
|
61
|
-
export const
|
|
62
|
-
args: {
|
|
63
|
-
children: 'Custom styled',
|
|
64
|
-
className: 'font-bold text-xl',
|
|
65
|
-
},
|
|
39
|
+
export const Disabled: Story = {
|
|
40
|
+
args: { disabled: true },
|
|
66
41
|
};
|
|
67
42
|
|
|
68
|
-
export const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
43
|
+
export const IconSizes: Story = {
|
|
44
|
+
render: (args) => (
|
|
45
|
+
<div className="flex items-center gap-3">
|
|
46
|
+
<ButtonLink {...args} variant="icon" size="sm">
|
|
47
|
+
<LuExternalLink />
|
|
48
|
+
</ButtonLink>
|
|
49
|
+
|
|
50
|
+
<ButtonLink {...args} variant="icon" size="base">
|
|
51
|
+
<LuExternalLink />
|
|
52
|
+
</ButtonLink>
|
|
53
|
+
|
|
54
|
+
<ButtonLink {...args} variant="icon" size="lg">
|
|
55
|
+
<LuExternalLink />
|
|
56
|
+
</ButtonLink>
|
|
57
|
+
</div>
|
|
58
|
+
),
|
|
72
59
|
};
|