@scottish-government/designsystem-react 0.8.0 → 0.10.0-beta.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/.storybook/main.ts +20 -0
- package/.storybook/manager.ts +13 -0
- package/.storybook/preview-head.html +1 -0
- package/.storybook/preview.tsx +56 -0
- package/.storybook/sgdsArgTypes.ts +123 -0
- package/.storybook/sgdsTheme.ts +9 -0
- package/.storybook/vitest.setup.ts +7 -0
- package/@types/common/AbstractNotificationBanner.d.ts +2 -2
- package/@types/common/ActionLink.d.ts +1 -1
- package/@types/common/Icon.d.ts +1 -1
- package/@types/components/Accordion.d.ts +2 -3
- package/@types/components/Button.d.ts +5 -5
- package/@types/components/CategoryItem.d.ts +10 -0
- package/@types/components/CategoryList.d.ts +7 -0
- package/@types/components/Checkbox.d.ts +2 -2
- package/@types/components/ContentsNav.d.ts +1 -1
- package/@types/components/DatePicker.d.ts +1 -1
- package/@types/components/ErrorMessage.d.ts +1 -2
- package/@types/components/ErrorSummary.d.ts +1 -1
- package/@types/components/FileDownload.d.ts +2 -2
- package/@types/components/Metadata.d.ts +1 -1
- package/@types/components/Pagination.d.ts +1 -1
- package/@types/components/RadioButton.d.ts +2 -2
- package/@types/components/SideNavigation.d.ts +1 -1
- package/@types/components/SiteNavigation.d.ts +1 -1
- package/@types/components/SummaryList.d.ts +1 -1
- package/@types/components/Tabs.d.ts +3 -3
- package/@types/components/TextInput.d.ts +1 -1
- package/@types/sgds.d.ts +2 -1
- package/CHANGELOG.md +29 -0
- package/dist/common/AbstractNotificationBanner.jsx +4 -4
- package/dist/common/Icon.jsx +2 -2
- package/dist/components/Accordion/Accordion.jsx +8 -7
- package/dist/components/Button/Button.jsx +6 -6
- package/dist/components/CategoryItem/CategoryItem.jsx +35 -0
- package/dist/components/CategoryList/CategoryList.jsx +55 -0
- package/dist/components/Checkbox/Checkbox.jsx +7 -4
- package/dist/components/Checkbox/CheckboxGroup.jsx +5 -11
- package/dist/components/ContentsNav/ContentsNav.jsx +2 -2
- package/dist/components/DatePicker/DatePicker.jsx +1 -1
- package/dist/components/ErrorMessage/ErrorMessage.jsx +3 -3
- package/dist/components/FileDownload/FileDownload.jsx +2 -2
- package/dist/components/NotificationBanner/NotificationBanner.jsx +2 -2
- package/dist/components/PageMetadata/PageMetadata.jsx +4 -4
- package/dist/components/Pagination/Pagination.jsx +4 -4
- package/dist/components/Question/Question.jsx +1 -1
- package/dist/components/RadioButton/RadioButton.jsx +6 -2
- package/dist/components/RadioButton/RadioGroup.jsx +7 -47
- package/dist/components/Select/Select.jsx +1 -1
- package/dist/components/SideNavigation/SideNavigation.jsx +2 -2
- package/dist/components/SiteHeader/SiteHeader.jsx +3 -3
- package/dist/components/SiteNavigation/SiteNavigation.jsx +2 -2
- package/dist/components/SiteSearch/SiteSearch.jsx +1 -1
- package/dist/components/SkipLinks/SkipLinks.jsx +1 -1
- package/dist/components/SummaryList/SummaryList.jsx +3 -3
- package/dist/components/Tabs/Tabs.jsx +6 -7
- package/dist/components/TextInput/TextInput.jsx +5 -5
- package/dist/components/Textarea/Textarea.jsx +1 -1
- package/dist/hooks/useTracking.js +21 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/context.js +5 -0
- package/package.json +15 -4
- package/src/common/AbstractNotificationBanner.test.tsx +1 -1
- package/src/common/AbstractNotificationBanner.tsx +4 -4
- package/src/common/Icon.test.tsx +1 -1
- package/src/common/Icon.tsx +2 -2
- package/src/components/Accordion/Accordion.stories.tsx +111 -0
- package/src/components/Accordion/Accordion.test.tsx +5 -17
- package/src/components/Accordion/Accordion.tsx +11 -10
- package/src/components/AspectBox/AspectBox.stories.tsx +64 -0
- package/src/components/BackToTop/BackToTop.stories.tsx +36 -0
- package/src/components/Breadcrumbs/Breadcrumbs.stories.tsx +49 -0
- package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +0 -1
- package/src/components/Breadcrumbs/Breadcrumbs.tsx +1 -1
- package/src/components/Button/Button.stories.tsx +194 -0
- package/src/components/Button/Button.test.tsx +4 -4
- package/src/components/Button/Button.tsx +9 -9
- package/src/components/CategoryItem/CategoryItem.stories.tsx +55 -0
- package/src/components/CategoryItem/CategoryItem.test.tsx +93 -0
- package/src/components/CategoryItem/CategoryItem.tsx +56 -0
- package/src/components/CategoryList/CategoryList.stories.tsx +65 -0
- package/src/components/CategoryList/CategoryList.test.tsx +59 -0
- package/src/components/CategoryList/CategoryList.tsx +33 -0
- package/src/components/Checkbox/Checkbox.stories.tsx +85 -0
- package/src/components/Checkbox/Checkbox.test.tsx +2 -2
- package/src/components/Checkbox/Checkbox.tsx +11 -6
- package/src/components/Checkbox/CheckboxGroup.stories.tsx +68 -0
- package/src/components/Checkbox/CheckboxGroup.tsx +7 -12
- package/src/components/ConfirmationMessage/ConfirmationMessage.stories.tsx +38 -0
- package/src/components/ContentsNav/ContentsNav.stories.tsx +43 -0
- package/src/components/ContentsNav/ContentsNav.test.tsx +2 -2
- package/src/components/ContentsNav/ContentsNav.tsx +2 -2
- package/src/components/CookieBanner/CookieBanner.stories.tsx +33 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +113 -0
- package/src/components/DatePicker/DatePicker.tsx +1 -1
- package/src/components/Details/Details.stories.tsx +36 -0
- package/src/components/ErrorMessage/ErrorMessage.stories.tsx +19 -0
- package/src/components/ErrorMessage/ErrorMessage.test.tsx +3 -15
- package/src/components/ErrorMessage/ErrorMessage.tsx +1 -3
- package/src/components/ErrorSummary/ErrorSummary.stories.tsx +38 -0
- package/src/components/FileDownload/FileDownload.stories.tsx +75 -0
- package/src/components/FileDownload/FileDownload.test.tsx +1 -1
- package/src/components/FileDownload/FileDownload.tsx +2 -2
- package/src/components/HideThisPage/HideThisPage.stories.tsx +20 -0
- package/src/components/InsetText/InsetText.stories.tsx +21 -0
- package/src/components/NotificationBanner/NotificationBanner.stories.tsx +57 -0
- package/src/components/NotificationBanner/NotificationBanner.test.tsx +1 -1
- package/src/components/NotificationBanner/NotificationBanner.tsx +4 -4
- package/src/components/NotificationPanel/NotificationPanel.stories.tsx +32 -0
- package/src/components/PageHeader/PageHeader.stories.tsx +60 -0
- package/src/components/PageMetadata/PageMetadata.stories.tsx +58 -0
- package/src/components/PageMetadata/PageMetadata.test.tsx +2 -2
- package/src/components/PageMetadata/PageMetadata.tsx +4 -4
- package/src/components/Pagination/Pagination.stories.tsx +69 -0
- package/src/components/Pagination/Pagination.test.tsx +1 -1
- package/src/components/Pagination/Pagination.tsx +4 -4
- package/src/components/PhaseBanner/PhaseBanner.stories.tsx +38 -0
- package/src/components/Question/Question.stories.tsx +78 -0
- package/src/components/Question/Question.tsx +1 -1
- package/src/components/RadioButton/RadioButton.stories.tsx +67 -0
- package/src/components/RadioButton/RadioButton.test.tsx +2 -1
- package/src/components/RadioButton/RadioButton.tsx +9 -3
- package/src/components/RadioButton/RadioGroup.stories.tsx +77 -0
- package/src/components/RadioButton/RadioGroup.test.tsx +2 -2
- package/src/components/RadioButton/RadioGroup.tsx +8 -15
- package/src/components/Select/Select.stories.tsx +76 -0
- package/src/components/Select/Select.tsx +1 -1
- package/src/components/SequentialNavigation/SequentialNavigation.stories.tsx +31 -0
- package/src/components/SideNavigation/SideNavigation.stories.tsx +92 -0
- package/src/components/SideNavigation/SideNavigation.test.tsx +2 -2
- package/src/components/SideNavigation/SideNavigation.tsx +2 -2
- package/src/components/SiteFooter/SiteFooter.stories.tsx +65 -0
- package/src/components/SiteHeader/SiteHeader.stories.tsx +92 -0
- package/src/components/SiteHeader/SiteHeader.tsx +2 -7
- package/src/components/SiteNavigation/SiteNavigation.stories.tsx +45 -0
- package/src/components/SiteNavigation/SiteNavigation.test.tsx +1 -1
- package/src/components/SiteNavigation/SiteNavigation.tsx +2 -2
- package/src/components/SiteSearch/SiteSearch.stories.tsx +81 -0
- package/src/components/SiteSearch/SiteSearch.tsx +1 -1
- package/src/components/SkipLinks/SkipLinks.stories.tsx +57 -0
- package/src/components/SkipLinks/SkipLinks.tsx +1 -1
- package/src/components/SummaryCard/SummaryCard.stories.tsx +46 -0
- package/src/components/SummaryList/SummaryList.stories.tsx +75 -0
- package/src/components/SummaryList/SummaryList.test.tsx +1 -1
- package/src/components/SummaryList/SummaryList.tsx +3 -3
- package/src/components/Table/Table.stories.tsx +96 -0
- package/src/components/Tabs/Tabs.stories.tsx +90 -0
- package/src/components/Tabs/Tabs.test.tsx +6 -8
- package/src/components/Tabs/Tabs.tsx +8 -9
- package/src/components/Tag/Tag.stories.tsx +25 -0
- package/src/components/TaskList/TaskList.stories.tsx +129 -0
- package/src/components/TextInput/TextInput.stories.tsx +123 -0
- package/src/components/TextInput/TextInput.test.tsx +2 -2
- package/src/components/TextInput/TextInput.tsx +5 -5
- package/src/components/Textarea/Textarea.stories.tsx +71 -0
- package/src/components/Textarea/Textarea.tsx +1 -1
- package/src/components/WarningText/WarningText.stories.tsx +21 -0
- package/src/hooks/useTracking.test.tsx +64 -0
- package/src/hooks/useTracking.ts +19 -0
- package/src/utils/context.ts +3 -0
- package/static/data/autocomplete-dummy-data.json +2361 -0
- package/static/images/highland-cow.jpg +0 -0
- package/static/images/scottish-government--min.svg +11 -0
- package/static/images/scottish-government.svg +6 -0
- package/tsconfig.json +3 -2
- package/vite.config.ts +45 -11
- package/vitest-setup.ts +1 -0
- package/vitest.shims.d.ts +1 -0
- package/src/utils/slugify.ts +0 -13
|
@@ -4,8 +4,8 @@ export const Page = ({
|
|
|
4
4
|
ariaLabel,
|
|
5
5
|
children,
|
|
6
6
|
className,
|
|
7
|
-
current = false,
|
|
8
7
|
href,
|
|
8
|
+
isCurrent = false,
|
|
9
9
|
linkComponent,
|
|
10
10
|
onClick
|
|
11
11
|
}: SGDS.Component.Pagination.Page) => {
|
|
@@ -19,7 +19,7 @@ export const Page = ({
|
|
|
19
19
|
const classNames = [
|
|
20
20
|
'ds_pagination__link',
|
|
21
21
|
className,
|
|
22
|
-
|
|
22
|
+
isCurrent ? 'ds_current' : undefined
|
|
23
23
|
].join(' ');
|
|
24
24
|
|
|
25
25
|
const linkProps: SGDS.LinkComponentProps = {
|
|
@@ -28,7 +28,7 @@ export const Page = ({
|
|
|
28
28
|
onClick: handleClick
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
if (
|
|
31
|
+
if (isCurrent) {
|
|
32
32
|
linkProps['aria-current'] = 'page';
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -144,7 +144,7 @@ const Pagination = ({
|
|
|
144
144
|
<Page
|
|
145
145
|
ariaLabel={`Page ${item}`}
|
|
146
146
|
href={pattern.replace('$1', String(item))}
|
|
147
|
-
|
|
147
|
+
isCurrent={item === page}
|
|
148
148
|
key={`pagination${index}`}
|
|
149
149
|
linkComponent={linkComponent}
|
|
150
150
|
onClick={onClick}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import PhaseBanner from './PhaseBanner';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/Phase banner',
|
|
8
|
+
component: PhaseBanner,
|
|
9
|
+
argTypes: {
|
|
10
|
+
children: argTypes.children(),
|
|
11
|
+
phaseName: {
|
|
12
|
+
description: 'The text for the banner\'s tag component.',
|
|
13
|
+
type: 'string'
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
args: {
|
|
17
|
+
phaseName: 'Beta'
|
|
18
|
+
}
|
|
19
|
+
} satisfies Meta<typeof PhaseBanner>;
|
|
20
|
+
|
|
21
|
+
export default meta;
|
|
22
|
+
type Story = StoryObj<typeof meta>;
|
|
23
|
+
|
|
24
|
+
export const Default: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
phaseName: 'Beta'
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const CustomContent: Story = {
|
|
31
|
+
args: {
|
|
32
|
+
phaseName: 'Beta',
|
|
33
|
+
children: <>This is a new service. Your <a href="#foo">feedback</a> will help us to improve it.</>
|
|
34
|
+
},
|
|
35
|
+
render: (args: any) => (
|
|
36
|
+
<PhaseBanner {...args}></PhaseBanner>
|
|
37
|
+
)
|
|
38
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import Question from './Question';
|
|
5
|
+
import TextInput from '../TextInput/TextInput';
|
|
6
|
+
import Checkbox from '../Checkbox/Checkbox';
|
|
7
|
+
import CheckboxGroup from '../Checkbox/CheckboxGroup';
|
|
8
|
+
|
|
9
|
+
const meta = {
|
|
10
|
+
title: 'Components/Question',
|
|
11
|
+
component: Question,
|
|
12
|
+
argTypes: {
|
|
13
|
+
errorMessage: argTypes.errorMessage(),
|
|
14
|
+
hasError: argTypes.hasError(),
|
|
15
|
+
hintText: argTypes.hintText(),
|
|
16
|
+
legend: {
|
|
17
|
+
desctiption: 'Text for a question\'s legend element (if the question uses a fieldset)',
|
|
18
|
+
type: 'string'
|
|
19
|
+
},
|
|
20
|
+
tagName: {
|
|
21
|
+
control: { type: 'select' },
|
|
22
|
+
description: 'HTML tag name to use for the question',
|
|
23
|
+
options: ['div', 'fieldset'],
|
|
24
|
+
type: 'string'
|
|
25
|
+
},
|
|
26
|
+
children: argTypes.children()
|
|
27
|
+
},
|
|
28
|
+
args: {
|
|
29
|
+
children: <TextInput
|
|
30
|
+
id="text-input-question"
|
|
31
|
+
label="First name"
|
|
32
|
+
/>,
|
|
33
|
+
tagName: 'div'
|
|
34
|
+
}
|
|
35
|
+
} satisfies Meta<typeof Question>;
|
|
36
|
+
|
|
37
|
+
export default meta;
|
|
38
|
+
type Story = StoryObj<typeof meta>;
|
|
39
|
+
|
|
40
|
+
export const Default: Story = {
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const ErrorQuestion: Story = {
|
|
44
|
+
args: {
|
|
45
|
+
errorMessage: 'This is a required field',
|
|
46
|
+
hasError: true
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const FieldsetQuestion: Story = {
|
|
51
|
+
args: {
|
|
52
|
+
children: <CheckboxGroup>
|
|
53
|
+
<Checkbox
|
|
54
|
+
checked
|
|
55
|
+
id="universal-credit"
|
|
56
|
+
label="Universal Credit"
|
|
57
|
+
/>
|
|
58
|
+
<Checkbox
|
|
59
|
+
id="pension-credit"
|
|
60
|
+
label="Pension Credit"
|
|
61
|
+
/>
|
|
62
|
+
<Checkbox
|
|
63
|
+
id="jsa"
|
|
64
|
+
label="Income-based Job Seeker's Allowance"
|
|
65
|
+
/>
|
|
66
|
+
<Checkbox
|
|
67
|
+
isExclusive
|
|
68
|
+
id="none"
|
|
69
|
+
label="No, I do not receive any of these benefits"
|
|
70
|
+
/>
|
|
71
|
+
</CheckboxGroup>,
|
|
72
|
+
errorMessage: 'You must select at least one option',
|
|
73
|
+
hasError: true,
|
|
74
|
+
hintText: 'Select all that apply.',
|
|
75
|
+
legend: 'Do you receive any of these benefits',
|
|
76
|
+
tagName: 'fieldset'
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -24,7 +24,7 @@ const Question = function ({
|
|
|
24
24
|
>
|
|
25
25
|
{legend && <legend>{legend}</legend>}
|
|
26
26
|
{hintText && <HintText text={hintText} />}
|
|
27
|
-
{hasError && errorMessage && <ErrorMessage
|
|
27
|
+
{hasError && errorMessage && <ErrorMessage>{errorMessage}</ErrorMessage>}
|
|
28
28
|
{children}
|
|
29
29
|
</WrapperTag>
|
|
30
30
|
);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import RadioButton from './RadioButton';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/Radio button',
|
|
8
|
+
component: RadioButton,
|
|
9
|
+
argTypes: {
|
|
10
|
+
checked: {
|
|
11
|
+
control: 'boolean',
|
|
12
|
+
description: 'The radio is checked on load'
|
|
13
|
+
},
|
|
14
|
+
hintText: argTypes.hintText(),
|
|
15
|
+
id: argTypes.id(),
|
|
16
|
+
label: argTypes.label(),
|
|
17
|
+
name: { type: 'string' },
|
|
18
|
+
onBlur: argTypes.onBlur(),
|
|
19
|
+
onChange: argTypes.onChange(),
|
|
20
|
+
isSmall: argTypes.isSmall()
|
|
21
|
+
},
|
|
22
|
+
args: {
|
|
23
|
+
id: 'arrears-radio',
|
|
24
|
+
label: 'Arrears',
|
|
25
|
+
name: 'radio-name',
|
|
26
|
+
}
|
|
27
|
+
} satisfies Meta<typeof RadioButton>;
|
|
28
|
+
|
|
29
|
+
export default meta;
|
|
30
|
+
type Story = StoryObj<typeof meta>;
|
|
31
|
+
|
|
32
|
+
export const Default: Story = {
|
|
33
|
+
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const KitchenSink: Story = {
|
|
37
|
+
args: {
|
|
38
|
+
checked: true,
|
|
39
|
+
hintText: 'This means you\'re paid for the period coming up, e.g. the month ahead',
|
|
40
|
+
isSmall: false
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const SmallRadio: Story = {
|
|
45
|
+
args: {
|
|
46
|
+
isSmall: true
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const Blur: Story = {
|
|
51
|
+
args: {
|
|
52
|
+
onBlur: () => {console.log('radio button blur')}
|
|
53
|
+
},
|
|
54
|
+
play: async ({ canvas, userEvent }) => {
|
|
55
|
+
await userEvent.click(canvas.getByRole('radio'));
|
|
56
|
+
await userEvent.tab();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const Change: Story = {
|
|
61
|
+
args: {
|
|
62
|
+
onChange: () => {console.log('radio button change')}
|
|
63
|
+
},
|
|
64
|
+
play: async ({ canvas, userEvent }) => {
|
|
65
|
+
await userEvent.click(canvas.getByRole('radio'));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -12,6 +12,7 @@ test('individual radio renders correctly', () => {
|
|
|
12
12
|
const label = screen.getByText('Pension Credit');
|
|
13
13
|
|
|
14
14
|
expect(radioContainer).toHaveClass('ds_radio');
|
|
15
|
+
expect(radioContainer).not.toHaveClass('ds_radio--small');
|
|
15
16
|
expect(radio.tagName).toEqual('INPUT');
|
|
16
17
|
expect(radio).toHaveAttribute('type', 'radio');
|
|
17
18
|
expect(radio.id).toEqual('pensioncredit');
|
|
@@ -74,7 +75,7 @@ test('radio with hint text', () => {
|
|
|
74
75
|
|
|
75
76
|
test('small radio', () => {
|
|
76
77
|
render(
|
|
77
|
-
<RadioButton
|
|
78
|
+
<RadioButton isSmall name="benefitType" label="Pension Credit" id="pensioncredit" />
|
|
78
79
|
);
|
|
79
80
|
|
|
80
81
|
const radio = screen.getByRole('radio');
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
|
|
1
3
|
import HintText from '../../common/HintText';
|
|
4
|
+
import { CheckboxRadioContext } from '../../utils/context';
|
|
2
5
|
|
|
3
6
|
const RadioButton = ({
|
|
4
7
|
checked,
|
|
5
8
|
hintText,
|
|
6
9
|
id,
|
|
10
|
+
isSmall,
|
|
7
11
|
label,
|
|
8
12
|
name,
|
|
9
13
|
onBlur,
|
|
10
|
-
onChange
|
|
11
|
-
small
|
|
14
|
+
onChange
|
|
12
15
|
}: SGDS.Component.RadioButton) => {
|
|
13
16
|
const hintTextId = `hint-text-${id}`;
|
|
14
17
|
|
|
@@ -24,11 +27,14 @@ const RadioButton = ({
|
|
|
24
27
|
}
|
|
25
28
|
}
|
|
26
29
|
|
|
30
|
+
isSmall = isSmall || useContext(CheckboxRadioContext).isSmall;
|
|
31
|
+
name = name || useContext(CheckboxRadioContext).name;
|
|
32
|
+
|
|
27
33
|
return (
|
|
28
34
|
<div
|
|
29
35
|
className={[
|
|
30
36
|
'ds_radio',
|
|
31
|
-
|
|
37
|
+
isSmall && 'ds_radio--small'
|
|
32
38
|
].join(' ')}>
|
|
33
39
|
<input
|
|
34
40
|
aria-describedby={hintText ? hintTextId : undefined}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import RadioButton from '../RadioButton/RadioButton';
|
|
5
|
+
import RadioGroup from './RadioGroup';
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: 'Components/Radio group',
|
|
9
|
+
component: RadioGroup,
|
|
10
|
+
argTypes: {
|
|
11
|
+
isInline: {
|
|
12
|
+
control: 'boolean',
|
|
13
|
+
description: 'Whether to display the radio buttons in the group inline'
|
|
14
|
+
},
|
|
15
|
+
name: {type: 'string'},
|
|
16
|
+
isSmall: argTypes.isSmall(),
|
|
17
|
+
children: argTypes.children()
|
|
18
|
+
},
|
|
19
|
+
args: {
|
|
20
|
+
children: <>
|
|
21
|
+
<RadioButton
|
|
22
|
+
id="flat-radio"
|
|
23
|
+
label="Flat"
|
|
24
|
+
/>
|
|
25
|
+
<RadioButton
|
|
26
|
+
id="bungalow-radio"
|
|
27
|
+
label="Bungalow"
|
|
28
|
+
/>
|
|
29
|
+
<RadioButton
|
|
30
|
+
id="cottage-radio"
|
|
31
|
+
label="Cottage"
|
|
32
|
+
/>
|
|
33
|
+
<RadioButton
|
|
34
|
+
id="terraced-radio"
|
|
35
|
+
label="Terraced house"
|
|
36
|
+
/>
|
|
37
|
+
<RadioButton
|
|
38
|
+
id="semi-radio"
|
|
39
|
+
label="Semi-detached house"
|
|
40
|
+
/>
|
|
41
|
+
<RadioButton
|
|
42
|
+
id="detached-radio"
|
|
43
|
+
label="Detached house"
|
|
44
|
+
/>
|
|
45
|
+
</>,
|
|
46
|
+
name: 'propertyType'
|
|
47
|
+
}
|
|
48
|
+
} satisfies Meta<typeof RadioGroup>;
|
|
49
|
+
|
|
50
|
+
export default meta;
|
|
51
|
+
type Story = StoryObj<typeof meta>;
|
|
52
|
+
|
|
53
|
+
export const Default: Story = {
|
|
54
|
+
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const SmallRadios: Story = {
|
|
58
|
+
args: {
|
|
59
|
+
isSmall: true
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const InlineRadios: Story = {
|
|
64
|
+
args: {
|
|
65
|
+
children: <>
|
|
66
|
+
<RadioButton
|
|
67
|
+
id="yes-radio"
|
|
68
|
+
label="Yes"
|
|
69
|
+
/>
|
|
70
|
+
<RadioButton
|
|
71
|
+
id="no-radio"
|
|
72
|
+
label="No"
|
|
73
|
+
/>
|
|
74
|
+
</>,
|
|
75
|
+
isInline: true
|
|
76
|
+
}
|
|
77
|
+
};
|
|
@@ -22,7 +22,7 @@ test('radio group passes all expected item params', () => {
|
|
|
22
22
|
const RADIO_NAME = 'radioname';
|
|
23
23
|
|
|
24
24
|
render(
|
|
25
|
-
<RadioGroup name={RADIO_NAME}
|
|
25
|
+
<RadioGroup name={RADIO_NAME} isSmall>
|
|
26
26
|
<RadioButton id="banana" />
|
|
27
27
|
<p>foo</p>
|
|
28
28
|
</RadioGroup>
|
|
@@ -36,7 +36,7 @@ test('radio group passes all expected item params', () => {
|
|
|
36
36
|
|
|
37
37
|
test('inline radio group', () => {
|
|
38
38
|
render(
|
|
39
|
-
<RadioGroup
|
|
39
|
+
<RadioGroup isInline>
|
|
40
40
|
<RadioButton id="banana" />
|
|
41
41
|
</RadioGroup>
|
|
42
42
|
);
|
|
@@ -1,34 +1,27 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { CheckboxRadioContext } from '../../utils/context';
|
|
3
3
|
|
|
4
4
|
const RadioGroup = ({
|
|
5
5
|
children,
|
|
6
6
|
className,
|
|
7
|
-
|
|
7
|
+
isInline,
|
|
8
|
+
isSmall,
|
|
8
9
|
name,
|
|
9
|
-
small,
|
|
10
10
|
...props
|
|
11
11
|
}: SGDS.Component.RadioButton.Group) => {
|
|
12
|
-
function processChild(child: any) {
|
|
13
|
-
if (child && child.type === RadioButton) {
|
|
14
|
-
return React.cloneElement(child as React.ReactElement<SGDS.Component.RadioButton>, { small: small, name: name });
|
|
15
|
-
} else {
|
|
16
|
-
return child;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
12
|
return (
|
|
21
13
|
<div
|
|
22
14
|
className={[
|
|
23
15
|
'ds_radios',
|
|
24
16
|
'ds_field-group',
|
|
25
|
-
|
|
17
|
+
isInline && 'ds_field-group--inline',
|
|
26
18
|
className
|
|
27
19
|
].join(' ')}
|
|
28
20
|
{...props}
|
|
29
21
|
>
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
<CheckboxRadioContext value={{ isSmall: !!isSmall, name }}>
|
|
23
|
+
{children}
|
|
24
|
+
</CheckboxRadioContext>
|
|
32
25
|
</div>
|
|
33
26
|
);
|
|
34
27
|
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import Select from './Select';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/Select',
|
|
8
|
+
component: Select,
|
|
9
|
+
argTypes: {
|
|
10
|
+
defaultValue: {type: 'string'},
|
|
11
|
+
errorMessage: argTypes.errorMessage(),
|
|
12
|
+
hasError: argTypes.hasError(),
|
|
13
|
+
hintText: argTypes.hintText(),
|
|
14
|
+
id: argTypes.id(),
|
|
15
|
+
label: argTypes.label(),
|
|
16
|
+
name: { type: 'string' },
|
|
17
|
+
onBlur: argTypes.onBlur(),
|
|
18
|
+
onChange: argTypes.onChange(),
|
|
19
|
+
placeholder: {type: 'string'},
|
|
20
|
+
width: argTypes.inputWidth(),
|
|
21
|
+
children: argTypes.children()
|
|
22
|
+
},
|
|
23
|
+
args: {
|
|
24
|
+
id: 'component',
|
|
25
|
+
label: 'Choose a component',
|
|
26
|
+
children: <>
|
|
27
|
+
<option value="accordion">
|
|
28
|
+
Accordion
|
|
29
|
+
</option>
|
|
30
|
+
<option value="breadcrumbs">
|
|
31
|
+
Breadcrumbs
|
|
32
|
+
</option>
|
|
33
|
+
<option value="button">
|
|
34
|
+
Button
|
|
35
|
+
</option>
|
|
36
|
+
</>
|
|
37
|
+
}
|
|
38
|
+
} satisfies Meta<typeof Select>;
|
|
39
|
+
|
|
40
|
+
export default meta;
|
|
41
|
+
type Story = StoryObj<typeof meta>;
|
|
42
|
+
|
|
43
|
+
export const Default: Story = {
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const KitchenSink: Story = {
|
|
47
|
+
args: {
|
|
48
|
+
defaultValue: 'button',
|
|
49
|
+
errorMessage: 'This field is required',
|
|
50
|
+
hasError: true,
|
|
51
|
+
hintText: 'Choose a component to learn more about how it works',
|
|
52
|
+
id: 'kitchensink',
|
|
53
|
+
placeholder: 'Choose',
|
|
54
|
+
width: 'fluid-one-third'
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const Blur: Story = {
|
|
59
|
+
args: {
|
|
60
|
+
onBlur: () => {console.log('select blur')}
|
|
61
|
+
},
|
|
62
|
+
play: async ({ canvas, userEvent }) => {
|
|
63
|
+
await userEvent.click(canvas.getByRole('combobox'));
|
|
64
|
+
await userEvent.tab();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const Change: Story = {
|
|
69
|
+
args: {
|
|
70
|
+
onChange: () => {console.log('select change')}
|
|
71
|
+
},
|
|
72
|
+
play: async ({ canvas, userEvent }) => {
|
|
73
|
+
await userEvent.click(canvas.getByRole('combobox'));
|
|
74
|
+
await userEvent.selectOptions(canvas.getByRole('combobox'), ['button'])
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -40,7 +40,7 @@ const Select = function ({
|
|
|
40
40
|
<>
|
|
41
41
|
<label className="ds_label" htmlFor={id}>{label}</label>
|
|
42
42
|
{hintText && <HintText id={hintTextId} text={hintText} />}
|
|
43
|
-
{errorMessage && <ErrorMessage id={errorMessageId}
|
|
43
|
+
{errorMessage && <ErrorMessage id={errorMessageId}>{errorMessage}</ErrorMessage>}
|
|
44
44
|
<div
|
|
45
45
|
className={[
|
|
46
46
|
"ds_select-wrapper",
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import SequentialNavigation from './SequentialNavigation';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/Sequential navigation',
|
|
8
|
+
component: SequentialNavigation,
|
|
9
|
+
argTypes: {
|
|
10
|
+
ariaLabel: argTypes.ariaLabel({ description: 'Text to use for an aria-label attribute on the nav element' }),
|
|
11
|
+
linkComponent: argTypes.linkComponent(),
|
|
12
|
+
children: argTypes.children()
|
|
13
|
+
},
|
|
14
|
+
args: {
|
|
15
|
+
children: <>
|
|
16
|
+
<SequentialNavigation.Previous href="#previous">
|
|
17
|
+
Apply for or renew a Blue Badge
|
|
18
|
+
</SequentialNavigation.Previous>
|
|
19
|
+
<SequentialNavigation.Next href="#next">
|
|
20
|
+
Eligibility: who can have one?
|
|
21
|
+
</SequentialNavigation.Next>
|
|
22
|
+
</>
|
|
23
|
+
}
|
|
24
|
+
} satisfies Meta<typeof SequentialNavigation>;
|
|
25
|
+
|
|
26
|
+
export default meta;
|
|
27
|
+
type Story = StoryObj<typeof meta>;
|
|
28
|
+
|
|
29
|
+
export const Default: Story = {
|
|
30
|
+
|
|
31
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import SideNavigation from './SideNavigation';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/Side navigation',
|
|
8
|
+
component: SideNavigation,
|
|
9
|
+
argTypes: {
|
|
10
|
+
linkComponent: argTypes.linkComponent(),
|
|
11
|
+
children: argTypes.children()
|
|
12
|
+
},
|
|
13
|
+
args: {
|
|
14
|
+
children: <>
|
|
15
|
+
<SideNavigation.List isRoot>
|
|
16
|
+
<SideNavigation.Item
|
|
17
|
+
isCurrent
|
|
18
|
+
href="#apples"
|
|
19
|
+
title="Apples"
|
|
20
|
+
>
|
|
21
|
+
</SideNavigation.Item>
|
|
22
|
+
<SideNavigation.Item
|
|
23
|
+
href="#bananas"
|
|
24
|
+
title="Bananas"
|
|
25
|
+
/>
|
|
26
|
+
<SideNavigation.Item
|
|
27
|
+
href="#cherries"
|
|
28
|
+
title="Cherries"
|
|
29
|
+
/>
|
|
30
|
+
<SideNavigation.Item
|
|
31
|
+
href="#dates"
|
|
32
|
+
title="Dates"
|
|
33
|
+
/>
|
|
34
|
+
</SideNavigation.List>
|
|
35
|
+
</>
|
|
36
|
+
}
|
|
37
|
+
} satisfies Meta<typeof SideNavigation>;
|
|
38
|
+
|
|
39
|
+
export default meta;
|
|
40
|
+
type Story = StoryObj<typeof meta>;
|
|
41
|
+
|
|
42
|
+
export const Default: Story = {
|
|
43
|
+
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const NestedNavigation: Story = {
|
|
47
|
+
args: {
|
|
48
|
+
children: <>
|
|
49
|
+
<SideNavigation.List isRoot>
|
|
50
|
+
<SideNavigation.Item
|
|
51
|
+
href="#apples"
|
|
52
|
+
title="Apples"
|
|
53
|
+
>
|
|
54
|
+
<SideNavigation.List>
|
|
55
|
+
<SideNavigation.Item
|
|
56
|
+
href="#green-apples"
|
|
57
|
+
title="Green apples"
|
|
58
|
+
>
|
|
59
|
+
<SideNavigation.List>
|
|
60
|
+
<SideNavigation.Item
|
|
61
|
+
isCurrent
|
|
62
|
+
href="#bramley"
|
|
63
|
+
title="Bramley"
|
|
64
|
+
/>
|
|
65
|
+
<SideNavigation.Item
|
|
66
|
+
href="#granny-smith"
|
|
67
|
+
title="Granny smith"
|
|
68
|
+
/>
|
|
69
|
+
</SideNavigation.List>
|
|
70
|
+
</SideNavigation.Item>
|
|
71
|
+
<SideNavigation.Item
|
|
72
|
+
href="#red-apples"
|
|
73
|
+
title="Red apples"
|
|
74
|
+
/>
|
|
75
|
+
</SideNavigation.List>
|
|
76
|
+
</SideNavigation.Item>
|
|
77
|
+
<SideNavigation.Item
|
|
78
|
+
href="#bananas"
|
|
79
|
+
title="Bananas"
|
|
80
|
+
/>
|
|
81
|
+
<SideNavigation.Item
|
|
82
|
+
href="#cherries"
|
|
83
|
+
title="Cherries"
|
|
84
|
+
/>
|
|
85
|
+
<SideNavigation.Item
|
|
86
|
+
href="#dates"
|
|
87
|
+
title="Dates"
|
|
88
|
+
/>
|
|
89
|
+
</SideNavigation.List>
|
|
90
|
+
</>
|
|
91
|
+
}
|
|
92
|
+
};
|
|
@@ -10,7 +10,7 @@ test('side navigation renders correctly', () => {
|
|
|
10
10
|
<SideNavigation.List>
|
|
11
11
|
<SideNavigation.Item href="#green-apples" title="Green apples">
|
|
12
12
|
<SideNavigation.List>
|
|
13
|
-
<SideNavigation.Item href="#bramley" title="Bramley"
|
|
13
|
+
<SideNavigation.Item href="#bramley" title="Bramley" isCurrent/>
|
|
14
14
|
<SideNavigation.Item href="#granny-smith" title="Granny smith"/>
|
|
15
15
|
</SideNavigation.List>
|
|
16
16
|
</SideNavigation.Item>
|
|
@@ -60,7 +60,7 @@ test('side nav link renders correctly', () => {
|
|
|
60
60
|
|
|
61
61
|
test('current side nav item without link renders correctly', () => {
|
|
62
62
|
render(
|
|
63
|
-
<SideNavigation.Item href="#green-apples" title="Green apples"
|
|
63
|
+
<SideNavigation.Item href="#green-apples" title="Green apples" isCurrent />
|
|
64
64
|
);
|
|
65
65
|
|
|
66
66
|
const item = screen.getByRole('listitem');
|
|
@@ -18,7 +18,7 @@ const SideNavigationList = function ({
|
|
|
18
18
|
const SideNavigationItem = function ({
|
|
19
19
|
children,
|
|
20
20
|
href,
|
|
21
|
-
|
|
21
|
+
isCurrent = false,
|
|
22
22
|
linkComponent,
|
|
23
23
|
title
|
|
24
24
|
}: SGDS.Component.SideNavigation.Item) {
|
|
@@ -31,7 +31,7 @@ const SideNavigationItem = function ({
|
|
|
31
31
|
children && 'ds_side-navigation__item--has-children'
|
|
32
32
|
].join(' ')}
|
|
33
33
|
>
|
|
34
|
-
{
|
|
34
|
+
{isCurrent ?
|
|
35
35
|
<span className={LINK_CLASS + ' ds_current'}>{title}</span> :
|
|
36
36
|
linkComponent ? linkComponent({ className: LINK_CLASS, href, children: title }) :
|
|
37
37
|
<a href={href} className={LINK_CLASS}>{title}</a>
|