@scottish-government/designsystem-react 0.9.0-beta.0 → 0.10.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 -2
- 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 +3 -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 +5 -5
- package/dist/components/Checkbox/CheckboxGroup.jsx +2 -2
- 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 +3 -3
- package/dist/components/RadioButton/RadioGroup.jsx +3 -3
- 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/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/context.js +1 -1
- package/package.json +14 -3
- 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 -30
- package/src/components/Accordion/Accordion.tsx +4 -9
- 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.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 +7 -7
- package/src/components/Checkbox/CheckboxGroup.stories.tsx +68 -0
- package/src/components/Checkbox/CheckboxGroup.tsx +2 -2
- 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 +4 -4
- package/src/components/RadioButton/RadioGroup.stories.tsx +77 -0
- package/src/components/RadioButton/RadioGroup.test.tsx +2 -2
- package/src/components/RadioButton/RadioGroup.tsx +4 -4
- 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/utils/context.ts +1 -1
- 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 +2 -1
- 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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import CategoryList from './CategoryList';
|
|
5
|
+
import CategoryItem from '../CategoryItem/CategoryItem';
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: 'Components/Category list',
|
|
9
|
+
component: CategoryList,
|
|
10
|
+
argTypes: {
|
|
11
|
+
children: argTypes.children(),
|
|
12
|
+
isGrid: {
|
|
13
|
+
description: 'Show the category items in a grid',
|
|
14
|
+
type: 'boolean'
|
|
15
|
+
},
|
|
16
|
+
isOrdered: {
|
|
17
|
+
description: 'Use an ordered list for the category items in the list',
|
|
18
|
+
type: 'boolean'
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
args: {
|
|
22
|
+
}
|
|
23
|
+
} satisfies Meta<typeof CategoryList>;
|
|
24
|
+
|
|
25
|
+
export default meta;
|
|
26
|
+
type Story = StoryObj<typeof meta>;
|
|
27
|
+
|
|
28
|
+
export const Default: Story = {
|
|
29
|
+
render: (args) => (
|
|
30
|
+
<CategoryList {...args}>
|
|
31
|
+
<CategoryItem title="Public transport, bus passes and discounts" href="#foo">Find information about local travel by road, rail and water and National Entitlement Cards.</CategoryItem>
|
|
32
|
+
<CategoryItem title="Parking and Blue Badges" href="#bar">Find out about getting a disabled parking space and information on Blue Badges.</CategoryItem>
|
|
33
|
+
<CategoryItem title="Apply to reduce your driving disqualification period" href="#baz">How to apply to court to reduce your driving ban. Includes who can apply and how much it costs.</CategoryItem>
|
|
34
|
+
<CategoryItem title="Road safety: parking tickets, fines and bans" href="#qux">Find out about the drink-drive limit, how to stay safe on the roads and what to do if you receive parking tickets.</CategoryItem>
|
|
35
|
+
</CategoryList>
|
|
36
|
+
)
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const Grid: Story = {
|
|
40
|
+
args: {
|
|
41
|
+
isGrid: true
|
|
42
|
+
},
|
|
43
|
+
render: (args) => (
|
|
44
|
+
<CategoryList {...args}>
|
|
45
|
+
<CategoryItem title="Public transport, bus passes and discounts" href="#foo">Find information about local travel by road, rail and water and National Entitlement Cards.</CategoryItem>
|
|
46
|
+
<CategoryItem title="Parking and Blue Badges" href="#bar">Find out about getting a disabled parking space and information on Blue Badges.</CategoryItem>
|
|
47
|
+
<CategoryItem title="Apply to reduce your driving disqualification period" href="#baz">How to apply to court to reduce your driving ban. Includes who can apply and how much it costs.</CategoryItem>
|
|
48
|
+
<CategoryItem title="Road safety: parking tickets, fines and bans" href="#qux">Find out about the drink-drive limit, how to stay safe on the roads and what to do if you receive parking tickets.</CategoryItem>
|
|
49
|
+
</CategoryList>
|
|
50
|
+
)
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const OrderedList: Story = {
|
|
54
|
+
args: {
|
|
55
|
+
isOrdered: true
|
|
56
|
+
},
|
|
57
|
+
render: (args) => (
|
|
58
|
+
<CategoryList {...args}>
|
|
59
|
+
<CategoryItem title="Public transport, bus passes and discounts" href="#foo">Find information about local travel by road, rail and water and National Entitlement Cards.</CategoryItem>
|
|
60
|
+
<CategoryItem title="Parking and Blue Badges" href="#bar">Find out about getting a disabled parking space and information on Blue Badges.</CategoryItem>
|
|
61
|
+
<CategoryItem title="Apply to reduce your driving disqualification period" href="#baz">How to apply to court to reduce your driving ban. Includes who can apply and how much it costs.</CategoryItem>
|
|
62
|
+
<CategoryItem title="Road safety: parking tickets, fines and bans" href="#qux">Find out about the drink-drive limit, how to stay safe on the roads and what to do if you receive parking tickets.</CategoryItem>
|
|
63
|
+
</CategoryList>
|
|
64
|
+
)
|
|
65
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { test, expect } from 'vitest';
|
|
2
|
+
import { render, screen, within } from '@testing-library/react';
|
|
3
|
+
import CategoryList from './CategoryList';
|
|
4
|
+
import CategoryItem from '../CategoryItem/CategoryItem';
|
|
5
|
+
|
|
6
|
+
test('category list renders correctly', () => {
|
|
7
|
+
render(
|
|
8
|
+
<CategoryList>
|
|
9
|
+
<CategoryItem data-testid="category-item" title="Public transport, bus passes and discounts" href="#foo">Find information about local travel by road, rail and water and National Entitlement Cards.</CategoryItem>
|
|
10
|
+
<CategoryItem title="Parking and Blue Badges" href="#bar">Find out about getting a disabled parking space and information on Blue Badges.</CategoryItem>
|
|
11
|
+
<CategoryItem title="Apply to reduce your driving disqualification period" href="#baz">How to apply to court to reduce your driving ban. Includes who can apply and how much it costs.</CategoryItem>
|
|
12
|
+
<CategoryItem title="Road safety: parking tickets, fines and bans" href="#qux">Find out about the drink-drive limit, how to stay safe on the roads and what to do if you receive parking tickets.</CategoryItem>
|
|
13
|
+
</CategoryList>
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const categoryList = screen.getByRole('list');
|
|
17
|
+
expect(categoryList).toHaveClass('ds_category-list');
|
|
18
|
+
expect(categoryList).not.toHaveClass('ds_category-list--grid');
|
|
19
|
+
expect(categoryList.tagName).toEqual('UL');
|
|
20
|
+
|
|
21
|
+
const child = within(categoryList).getByTestId('category-item');
|
|
22
|
+
expect(child.tagName).toEqual('LI');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('ordered category list', () => {
|
|
26
|
+
render(
|
|
27
|
+
<CategoryList isOrdered data-test="foo" />
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const categoryList = screen.getByRole('list');
|
|
31
|
+
expect(categoryList.tagName).toEqual('OL');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('grid category list', () => {
|
|
35
|
+
render(
|
|
36
|
+
<CategoryList isGrid data-test="foo" />
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const categoryList = screen.getByRole('list');
|
|
40
|
+
expect(categoryList).toHaveClass('ds_category-list--grid');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('passing additional props', () => {
|
|
44
|
+
render(
|
|
45
|
+
<CategoryList data-test="foo" />
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const categoryList = screen.getByRole('list');
|
|
49
|
+
expect(categoryList.dataset.test).toEqual('foo');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('passing additional CSS classes', () => {
|
|
53
|
+
render(
|
|
54
|
+
<CategoryList className="foo" />
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const categoryList = screen.getByRole('list');
|
|
58
|
+
expect(categoryList).toHaveClass('foo');
|
|
59
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React, { Children } from 'react';
|
|
2
|
+
import WrapperTag from "../../common/WrapperTag";
|
|
3
|
+
|
|
4
|
+
const CategoryList = ({
|
|
5
|
+
children,
|
|
6
|
+
className,
|
|
7
|
+
isGrid,
|
|
8
|
+
isOrdered,
|
|
9
|
+
...props
|
|
10
|
+
}: SGDS.Component.CategoryList) => {
|
|
11
|
+
function processChild(child: React.ReactNode) {
|
|
12
|
+
const thisChild = child as React.ReactElement<SGDS.Component.CategoryItem>
|
|
13
|
+
return React.cloneElement(thisChild, {tagName: 'li'})
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<WrapperTag
|
|
18
|
+
tagName={isOrdered ? 'ol' : 'ul'}
|
|
19
|
+
className={[
|
|
20
|
+
'ds_category-list',
|
|
21
|
+
isGrid && 'ds_category-list--grid',
|
|
22
|
+
className
|
|
23
|
+
].join(' ')}
|
|
24
|
+
{...props}
|
|
25
|
+
>
|
|
26
|
+
{Children.map(children, child => processChild(child))}
|
|
27
|
+
</WrapperTag>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
CategoryList.displayName = 'CategoryList';
|
|
32
|
+
|
|
33
|
+
export default CategoryList;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import Checkbox from './Checkbox';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/Checkbox',
|
|
8
|
+
component: Checkbox,
|
|
9
|
+
argTypes: {
|
|
10
|
+
checked: {
|
|
11
|
+
control: 'boolean',
|
|
12
|
+
description: 'The checkbox is checked on load'
|
|
13
|
+
},
|
|
14
|
+
hintText: argTypes.hintText,
|
|
15
|
+
exclusive: {
|
|
16
|
+
control: 'boolean',
|
|
17
|
+
description: 'Whether the checkbox is exclusive (e.g. a \'none\' option)'
|
|
18
|
+
},
|
|
19
|
+
id: argTypes.id(),
|
|
20
|
+
label: argTypes.label(),
|
|
21
|
+
name: {
|
|
22
|
+
type: 'string'
|
|
23
|
+
},
|
|
24
|
+
onBlur: argTypes.onBlur(),
|
|
25
|
+
onChange: argTypes.onChange(),
|
|
26
|
+
small: argTypes.isSmall()
|
|
27
|
+
},
|
|
28
|
+
args: {
|
|
29
|
+
label: 'Benefits and grants',
|
|
30
|
+
id: 'benefits-and-grants'
|
|
31
|
+
}
|
|
32
|
+
} satisfies Meta<typeof Checkbox>;
|
|
33
|
+
|
|
34
|
+
export default meta;
|
|
35
|
+
type Story = StoryObj<typeof meta>;
|
|
36
|
+
|
|
37
|
+
export const Default: Story = {
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const CheckedByDefault: Story = {
|
|
41
|
+
args: {
|
|
42
|
+
checked: true,
|
|
43
|
+
id: 'checked'
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const SmallCheckbox: Story = {
|
|
48
|
+
args: {
|
|
49
|
+
isSmall: true,
|
|
50
|
+
id: 'small'
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const HintText: Story = {
|
|
55
|
+
args: {
|
|
56
|
+
hintText: 'Information on benefits, funds and grants, including Child Benefit and tax credits.',
|
|
57
|
+
id: 'hinttext'
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const CustomNameAttribute: Story = {
|
|
62
|
+
args: {
|
|
63
|
+
name: 'myName',
|
|
64
|
+
id: 'nameattribute'
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const Blur: Story = {
|
|
69
|
+
args: {
|
|
70
|
+
onBlur: () => {console.log('checkbox blur')}
|
|
71
|
+
},
|
|
72
|
+
play: async ({ canvas, userEvent }) => {
|
|
73
|
+
await userEvent.click(canvas.getByRole('checkbox'));
|
|
74
|
+
await userEvent.tab();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const Change: Story = {
|
|
79
|
+
args: {
|
|
80
|
+
onChange: () => {console.log('checkbox change')}
|
|
81
|
+
},
|
|
82
|
+
play: async ({ canvas, userEvent }) => {
|
|
83
|
+
await userEvent.click(canvas.getByRole('checkbox'));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -34,7 +34,7 @@ test('checked checkbox', () => {
|
|
|
34
34
|
|
|
35
35
|
test('exclusive checkbox', () => {
|
|
36
36
|
render(
|
|
37
|
-
<Checkbox
|
|
37
|
+
<Checkbox isExclusive label="Pension Credit" id="pensioncredit" />
|
|
38
38
|
);
|
|
39
39
|
|
|
40
40
|
const checkbox = screen.getByRole('checkbox');
|
|
@@ -88,7 +88,7 @@ test('checkbox with hint text', () => {
|
|
|
88
88
|
|
|
89
89
|
test('small checkbox', () => {
|
|
90
90
|
render(
|
|
91
|
-
<Checkbox
|
|
91
|
+
<Checkbox isSmall label="Pension Credit" id="pensioncredit" />
|
|
92
92
|
);
|
|
93
93
|
|
|
94
94
|
const checkbox = screen.getByRole('checkbox');
|
|
@@ -7,15 +7,15 @@ const Checkbox = ({
|
|
|
7
7
|
checked,
|
|
8
8
|
hintText,
|
|
9
9
|
id,
|
|
10
|
-
|
|
10
|
+
isSmall,
|
|
11
|
+
isExclusive,
|
|
11
12
|
label,
|
|
12
13
|
name,
|
|
13
14
|
onBlur,
|
|
14
|
-
onChange
|
|
15
|
-
small
|
|
15
|
+
onChange
|
|
16
16
|
}: SGDS.Component.Checkbox) => {
|
|
17
17
|
const hintTextId = `hint-text-${id}`;
|
|
18
|
-
const behaviour =
|
|
18
|
+
const behaviour = isExclusive && 'exclusive';
|
|
19
19
|
|
|
20
20
|
function handleBlur(event: React.FocusEvent) {
|
|
21
21
|
if (typeof onBlur === 'function') {
|
|
@@ -29,15 +29,15 @@ const Checkbox = ({
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
isSmall = isSmall || useContext(CheckboxRadioContext).isSmall;
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
35
|
<>
|
|
36
|
-
{
|
|
36
|
+
{isExclusive && <p className="ds_checkbox-separator">or</p>}
|
|
37
37
|
<div
|
|
38
38
|
className={[
|
|
39
39
|
'ds_checkbox',
|
|
40
|
-
|
|
40
|
+
isSmall && 'ds_checkbox--small'
|
|
41
41
|
].join(' ')}>
|
|
42
42
|
|
|
43
43
|
<input
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import CheckboxGroup from './CheckboxGroup';
|
|
5
|
+
import Checkbox from './Checkbox';
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
component: CheckboxGroup,
|
|
9
|
+
title: 'Components/CheckboxGroup',
|
|
10
|
+
argTypes: {
|
|
11
|
+
children: argTypes.children(),
|
|
12
|
+
isSmall: argTypes.isSmall()
|
|
13
|
+
},
|
|
14
|
+
args: {
|
|
15
|
+
children: <>
|
|
16
|
+
<Checkbox
|
|
17
|
+
checked
|
|
18
|
+
id="universal-credit"
|
|
19
|
+
label="Universal Credit"
|
|
20
|
+
/>
|
|
21
|
+
<Checkbox
|
|
22
|
+
id="pension-credit"
|
|
23
|
+
label="Pension Credit"
|
|
24
|
+
/>
|
|
25
|
+
<Checkbox
|
|
26
|
+
id="jsa"
|
|
27
|
+
label="Income-based Job Seeker's Allowance"
|
|
28
|
+
/>
|
|
29
|
+
</>
|
|
30
|
+
}
|
|
31
|
+
} satisfies Meta<typeof CheckboxGroup>;
|
|
32
|
+
|
|
33
|
+
export default meta;
|
|
34
|
+
type Story = StoryObj<typeof meta>;
|
|
35
|
+
|
|
36
|
+
export const Default: Story = {
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const SmallCheckboxes: Story = {
|
|
40
|
+
args: {
|
|
41
|
+
isSmall: true
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const ExclusiveCheckbox: Story = {
|
|
46
|
+
args: {
|
|
47
|
+
children: <>
|
|
48
|
+
<Checkbox
|
|
49
|
+
checked
|
|
50
|
+
id="universal-creditx"
|
|
51
|
+
label="Universal Credit"
|
|
52
|
+
/>
|
|
53
|
+
<Checkbox
|
|
54
|
+
id="pension-creditx"
|
|
55
|
+
label="Pension Credit"
|
|
56
|
+
/>
|
|
57
|
+
<Checkbox
|
|
58
|
+
id="jsax"
|
|
59
|
+
label="Income-based Job Seeker's Allowance"
|
|
60
|
+
/>
|
|
61
|
+
<Checkbox
|
|
62
|
+
isExclusive
|
|
63
|
+
id="nonex"
|
|
64
|
+
label="No, I do not receive any of these benefits"
|
|
65
|
+
/>
|
|
66
|
+
</>
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -7,7 +7,7 @@ import DSCheckboxes from '@scottish-government/design-system/src/forms/checkbox/
|
|
|
7
7
|
export const CheckboxGroup = ({
|
|
8
8
|
children,
|
|
9
9
|
className,
|
|
10
|
-
|
|
10
|
+
isSmall,
|
|
11
11
|
...props
|
|
12
12
|
}: SGDS.Component.Checkbox.Group) => {
|
|
13
13
|
const ref = useRef(null);
|
|
@@ -29,7 +29,7 @@ export const CheckboxGroup = ({
|
|
|
29
29
|
ref={ref}
|
|
30
30
|
{...props}
|
|
31
31
|
>
|
|
32
|
-
<CheckboxRadioContext value={{
|
|
32
|
+
<CheckboxRadioContext value={{isSmall: !!isSmall, name: ''}}>
|
|
33
33
|
{children}
|
|
34
34
|
</CheckboxRadioContext>
|
|
35
35
|
</div>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import ConfirmationMessage from './ConfirmationMessage';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/Confirmation Message',
|
|
8
|
+
component: ConfirmationMessage,
|
|
9
|
+
argTypes: {
|
|
10
|
+
headingLevel: argTypes.headingLevel(),
|
|
11
|
+
ariaLive: argTypes.ariaLive(),
|
|
12
|
+
children: argTypes.children()
|
|
13
|
+
},
|
|
14
|
+
args: {
|
|
15
|
+
ariaLive: 'polite',
|
|
16
|
+
children: (<p>You have added the landlord <strong>John Smith</strong> to the application.</p>),
|
|
17
|
+
headingLevel: 'h3',
|
|
18
|
+
title: 'Landlord added successfully',
|
|
19
|
+
}
|
|
20
|
+
} satisfies Meta<typeof ConfirmationMessage>;
|
|
21
|
+
|
|
22
|
+
export default meta;
|
|
23
|
+
type Story = StoryObj<typeof meta>;
|
|
24
|
+
|
|
25
|
+
export const Default: Story = {
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const NoChildren: Story = {
|
|
29
|
+
args: {
|
|
30
|
+
children: undefined
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const DifferentHeadingLevel: Story = {
|
|
35
|
+
args: {
|
|
36
|
+
headingLevel: 'h2'
|
|
37
|
+
}
|
|
38
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import ContentsNav from './ContentsNav';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/Contents nav',
|
|
8
|
+
component: ContentsNav,
|
|
9
|
+
argTypes: {
|
|
10
|
+
ariaLabel: argTypes.ariaLabel({description: 'Text to use for the content nav\'s aria-label property'}),
|
|
11
|
+
children: argTypes.children(),
|
|
12
|
+
linkComponent: argTypes.linkComponent(),
|
|
13
|
+
title: {
|
|
14
|
+
description: 'Title of the contents nav',
|
|
15
|
+
type: 'string'
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
args: {
|
|
19
|
+
children: <>
|
|
20
|
+
<ContentsNav.Item current>
|
|
21
|
+
Apply for Blue Badge
|
|
22
|
+
</ContentsNav.Item>
|
|
23
|
+
<ContentsNav.Item href="#2">
|
|
24
|
+
Eligibility
|
|
25
|
+
</ContentsNav.Item>
|
|
26
|
+
<ContentsNav.Item href="#3">
|
|
27
|
+
Using your Blue Badge
|
|
28
|
+
</ContentsNav.Item>
|
|
29
|
+
<ContentsNav.Item href="#4">
|
|
30
|
+
Report a lost, stolen or misuesd Blue Badge
|
|
31
|
+
</ContentsNav.Item>
|
|
32
|
+
<ContentsNav.Item href="#5">
|
|
33
|
+
Changing or handing back a Blue Badge
|
|
34
|
+
</ContentsNav.Item>
|
|
35
|
+
</>
|
|
36
|
+
}
|
|
37
|
+
} satisfies Meta<typeof ContentsNav>;
|
|
38
|
+
|
|
39
|
+
export default meta;
|
|
40
|
+
type Story = StoryObj<typeof meta>;
|
|
41
|
+
|
|
42
|
+
export const Default: Story = {
|
|
43
|
+
};
|
|
@@ -72,7 +72,7 @@ test('contents nav item without href', () => {
|
|
|
72
72
|
|
|
73
73
|
test('current contents nav item with href', () => {
|
|
74
74
|
render(
|
|
75
|
-
<ContentsNav.Item
|
|
75
|
+
<ContentsNav.Item isCurrent href={ITEM_HREF}>{ITEM_TITLE}</ContentsNav.Item>
|
|
76
76
|
);
|
|
77
77
|
|
|
78
78
|
const listItem = screen.getByRole('listitem');
|
|
@@ -84,7 +84,7 @@ test('current contents nav item with href', () => {
|
|
|
84
84
|
|
|
85
85
|
test('current contents nav item without href', () => {
|
|
86
86
|
render(
|
|
87
|
-
<ContentsNav.Item
|
|
87
|
+
<ContentsNav.Item isCurrent>{ITEM_TITLE}</ContentsNav.Item>
|
|
88
88
|
);
|
|
89
89
|
|
|
90
90
|
const listItem = screen.getByRole('listitem');
|
|
@@ -2,14 +2,14 @@ import React from 'react';
|
|
|
2
2
|
|
|
3
3
|
const ContentsNavItem = ({
|
|
4
4
|
children,
|
|
5
|
-
|
|
5
|
+
isCurrent,
|
|
6
6
|
href,
|
|
7
7
|
linkComponent
|
|
8
8
|
}: SGDS.Component.ContentsNav.ContentsNavItem) => {
|
|
9
9
|
const classNames = ['ds_contents-nav__link'];
|
|
10
10
|
let ariaCurrent: React.AriaAttributes["aria-current"];
|
|
11
11
|
|
|
12
|
-
if (
|
|
12
|
+
if (isCurrent) {
|
|
13
13
|
classNames.push('ds_current');
|
|
14
14
|
ariaCurrent = 'page';
|
|
15
15
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import CookieBanner from './CookieBanner';
|
|
5
|
+
import Button from '../Button/Button';
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: 'Components/Cookie banner',
|
|
9
|
+
component: CookieBanner,
|
|
10
|
+
argTypes: {
|
|
11
|
+
children: argTypes.children()
|
|
12
|
+
},
|
|
13
|
+
args: {
|
|
14
|
+
children: [
|
|
15
|
+
<p key="foo">We use <a href="/cookies/">cookies</a> to collect anonymous data to help us improve your site browsing
|
|
16
|
+
experience.</p>,
|
|
17
|
+
<p key="bar">Click 'Accept all cookies' to agree to all cookies that collect anonymous data.
|
|
18
|
+
To only allow the cookies that make the site work, click 'Use essential cookies only.' Visit 'Set cookie preferences' to control specific cookies.</p>,
|
|
19
|
+
<CookieBanner.Buttons key="baz">
|
|
20
|
+
<Button className="js-accept-all-cookies" small buttonStyle="secondary">Accept all cookies</Button>
|
|
21
|
+
<Button className="js-accept-essential-cookies" small buttonStyle="secondary">Use essential cookies only</Button>
|
|
22
|
+
<a href="/cookies/">Set cookie preferences</a>
|
|
23
|
+
</CookieBanner.Buttons>
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
} satisfies Meta<typeof CookieBanner>;
|
|
27
|
+
|
|
28
|
+
export default meta;
|
|
29
|
+
type Story = StoryObj<typeof meta>;
|
|
30
|
+
|
|
31
|
+
export const Default: Story = {
|
|
32
|
+
|
|
33
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import DatePicker from './DatePicker';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/Date picker',
|
|
8
|
+
component: DatePicker,
|
|
9
|
+
argTypes: {
|
|
10
|
+
dateSelectCallback: {},
|
|
11
|
+
disabledDates: {
|
|
12
|
+
control: { type: 'text' },
|
|
13
|
+
description: 'Space-separated list of dates to disable in the date picker'
|
|
14
|
+
},
|
|
15
|
+
hasError: argTypes.hasError(),
|
|
16
|
+
errorMessage: argTypes.errorMessage(),
|
|
17
|
+
hintText: argTypes.hintText(),
|
|
18
|
+
id: argTypes.id(),
|
|
19
|
+
label: argTypes.label(),
|
|
20
|
+
maxDate: {
|
|
21
|
+
control: { type: 'text' },
|
|
22
|
+
description: 'Latest selectable date in the date picker'
|
|
23
|
+
},
|
|
24
|
+
minDate: {
|
|
25
|
+
control: { type: 'text' },
|
|
26
|
+
description: 'Earliest selectable date in the date picker'
|
|
27
|
+
},
|
|
28
|
+
multiple: {
|
|
29
|
+
control: 'boolean',
|
|
30
|
+
description: 'Whether to display the day, month and year as separate fields'
|
|
31
|
+
},
|
|
32
|
+
name: {
|
|
33
|
+
control: { type: 'text' }
|
|
34
|
+
},
|
|
35
|
+
onBlur: argTypes.onBlur(),
|
|
36
|
+
onChange: argTypes.onChange(),
|
|
37
|
+
value: {
|
|
38
|
+
control: { type: 'text' }
|
|
39
|
+
},
|
|
40
|
+
width: argTypes.inputWidth()
|
|
41
|
+
},
|
|
42
|
+
args: {
|
|
43
|
+
label: 'Date of birth',
|
|
44
|
+
id: 'date-of-birth'
|
|
45
|
+
}
|
|
46
|
+
} satisfies Meta<typeof DatePicker>;
|
|
47
|
+
|
|
48
|
+
export default meta;
|
|
49
|
+
type Story = StoryObj<typeof meta>;
|
|
50
|
+
|
|
51
|
+
export const Default: Story = {
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const InitialValue: Story = {
|
|
55
|
+
args: {
|
|
56
|
+
value: '01/12/2020'
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const HintText: Story = {
|
|
61
|
+
args: {
|
|
62
|
+
hintText: 'Use \'dd/mm/yyyy\' format.'
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const Error: Story = {
|
|
67
|
+
args: {
|
|
68
|
+
hasError: true,
|
|
69
|
+
errorMessage: 'Please enter a valid date.'
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const Multiple: Story = {
|
|
74
|
+
args: {
|
|
75
|
+
multiple: true
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const MultipleInitialValue: Story = {
|
|
80
|
+
args: {
|
|
81
|
+
multiple: true,
|
|
82
|
+
value: '01/12/2020'
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const DateRestrictions: Story = {
|
|
87
|
+
args: {
|
|
88
|
+
disabledDates: '12/07/2025 13/07/2025 19/07/2025 20/07/2025',
|
|
89
|
+
maxDate: '25/07/2025',
|
|
90
|
+
minDate: '07/07/2025'
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const Blur: Story = {
|
|
95
|
+
args: {
|
|
96
|
+
onBlur: () => {console.log('date picker blur')}
|
|
97
|
+
},
|
|
98
|
+
play: async ({ canvas, userEvent }) => {
|
|
99
|
+
await userEvent.click(canvas.getByRole('textbox'));
|
|
100
|
+
await userEvent.tab();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const Change: Story = {
|
|
105
|
+
args: {
|
|
106
|
+
onChange: () => {console.log('date picker change')}
|
|
107
|
+
},
|
|
108
|
+
play: async ({ canvas, userEvent }) => {
|
|
109
|
+
await userEvent.click(canvas.getByRole('textbox'));
|
|
110
|
+
await userEvent.type(canvas.getByRole('textbox'),'01/12/2020');
|
|
111
|
+
await userEvent.tab();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -64,7 +64,7 @@ const DatePicker = ({
|
|
|
64
64
|
{(multiple ? (
|
|
65
65
|
<fieldset className="ds_datepicker__input-wrapper">
|
|
66
66
|
<legend>{label}</legend>
|
|
67
|
-
{errorMessage && <ErrorMessage
|
|
67
|
+
{errorMessage && <ErrorMessage>{errorMessage}</ErrorMessage>}
|
|
68
68
|
<div>
|
|
69
69
|
<TextInput
|
|
70
70
|
className="js-datepicker-date"
|