@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
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
import Table from './Table';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Components/Table',
|
|
7
|
+
component: Table,
|
|
8
|
+
argTypes: {
|
|
9
|
+
smallscreen: {
|
|
10
|
+
description: 'The behaviour to use on small screens',
|
|
11
|
+
children: { control: false },
|
|
12
|
+
control: { type: 'select' },
|
|
13
|
+
options: [undefined,'boxes', 'scrolling'],
|
|
14
|
+
type: 'string',
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
args: {
|
|
18
|
+
children: <>
|
|
19
|
+
<caption>Public holidays in 2020</caption>
|
|
20
|
+
<thead>
|
|
21
|
+
<tr>
|
|
22
|
+
<th scope="col">
|
|
23
|
+
Date
|
|
24
|
+
</th>
|
|
25
|
+
<th scope="col">
|
|
26
|
+
Day
|
|
27
|
+
</th>
|
|
28
|
+
<th scope="col">
|
|
29
|
+
Holiday
|
|
30
|
+
</th>
|
|
31
|
+
</tr>
|
|
32
|
+
</thead>
|
|
33
|
+
<tbody>
|
|
34
|
+
<tr>
|
|
35
|
+
<td>
|
|
36
|
+
10 April
|
|
37
|
+
</td>
|
|
38
|
+
<td>
|
|
39
|
+
Friday
|
|
40
|
+
</td>
|
|
41
|
+
<td>
|
|
42
|
+
Good Friday
|
|
43
|
+
</td>
|
|
44
|
+
</tr>
|
|
45
|
+
<tr>
|
|
46
|
+
<td>
|
|
47
|
+
8 May
|
|
48
|
+
</td>
|
|
49
|
+
<td>
|
|
50
|
+
Friday
|
|
51
|
+
</td>
|
|
52
|
+
<td>
|
|
53
|
+
Early May Bank Holiday
|
|
54
|
+
</td>
|
|
55
|
+
</tr>
|
|
56
|
+
<tr>
|
|
57
|
+
<td>
|
|
58
|
+
25 May
|
|
59
|
+
</td>
|
|
60
|
+
<td>
|
|
61
|
+
Monday
|
|
62
|
+
</td>
|
|
63
|
+
<td>
|
|
64
|
+
Spring Bank Holiday
|
|
65
|
+
</td>
|
|
66
|
+
</tr>
|
|
67
|
+
<tr>
|
|
68
|
+
<td>
|
|
69
|
+
3 August
|
|
70
|
+
</td>
|
|
71
|
+
<td>
|
|
72
|
+
Monday
|
|
73
|
+
</td>
|
|
74
|
+
<td>
|
|
75
|
+
Summer Bank Holiday
|
|
76
|
+
</td>
|
|
77
|
+
</tr>
|
|
78
|
+
</tbody>
|
|
79
|
+
</>
|
|
80
|
+
}
|
|
81
|
+
} satisfies Meta<typeof Table>;
|
|
82
|
+
|
|
83
|
+
export default meta;
|
|
84
|
+
type Story = StoryObj<typeof meta>;
|
|
85
|
+
|
|
86
|
+
export const Default: Story = {
|
|
87
|
+
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const Boxes: Story = {
|
|
91
|
+
args: {smallscreen: 'boxes'}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const Scrolling: Story = {
|
|
95
|
+
args: {smallscreen: 'scrolling'}
|
|
96
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import Tabs from './Tabs';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/Tabs',
|
|
8
|
+
component: Tabs,
|
|
9
|
+
argTypes: {
|
|
10
|
+
baseId: {
|
|
11
|
+
description: 'A string that IDs for subcomponents are derived from.',
|
|
12
|
+
type: {
|
|
13
|
+
name: 'string',
|
|
14
|
+
required: true
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
headingLevel: argTypes.headingLevel({
|
|
18
|
+
description: 'Heading level to use for the tab container\'s title',
|
|
19
|
+
}),
|
|
20
|
+
isBorderless: {
|
|
21
|
+
description: 'Whether to give each tab a border',
|
|
22
|
+
control: 'boolean'
|
|
23
|
+
},
|
|
24
|
+
isManual: {
|
|
25
|
+
control: 'boolean',
|
|
26
|
+
description: 'Whether to require manual tab activation',
|
|
27
|
+
type: 'boolean'
|
|
28
|
+
},
|
|
29
|
+
title: {
|
|
30
|
+
description: 'The title of the tab list',
|
|
31
|
+
type: 'string'
|
|
32
|
+
},
|
|
33
|
+
children: argTypes.children()
|
|
34
|
+
},
|
|
35
|
+
args: {
|
|
36
|
+
baseId: 'my-tabs',
|
|
37
|
+
children: [
|
|
38
|
+
<Tabs.Item key="foo" tabLabel="Courses and funding">
|
|
39
|
+
<h3>Search for training courses and funding</h3>
|
|
40
|
+
<p>A wide range of training courses for your employees are available.</p>
|
|
41
|
+
<p>Opportunities include distance learning, short courses and vocational training.</p>
|
|
42
|
+
<p><a href="#">Visit My World of Work to search for training courses</a>.</p>
|
|
43
|
+
<p>You can also <a href="#">search for training courses, and funding towards training</a>.</p>
|
|
44
|
+
</Tabs.Item>,
|
|
45
|
+
<Tabs.Item key="bar" tabLabel="Choosing apprenticeships">
|
|
46
|
+
<h3>Choosing an apprenticeship for your business</h3>
|
|
47
|
+
<p>Apprenticeships can help you address skills gaps in your business. The government provides help with the cost of training an apprentice.</p>
|
|
48
|
+
<p>There are 3 different types of apprenticeship:</p>
|
|
49
|
+
<ul>
|
|
50
|
+
<li>Foundation Apprenticeships let school or college students do short-term work experience at your business as part of a qualification</li>
|
|
51
|
+
<li>Modern Apprenticeships let your new or current employees gain a qualification while working in a paid role at your business</li>
|
|
52
|
+
<li>Graduate Apprenticeships let your new or current employees gain a degree while working in a paid role at your business</li>
|
|
53
|
+
</ul>
|
|
54
|
+
<p>You can find more information on the <a href="#">apprenticeships.scot</a> website.</p>
|
|
55
|
+
</Tabs.Item>,
|
|
56
|
+
<Tabs.Item key="baz" tabLabel="Extra skills support">
|
|
57
|
+
<h3>Extra skills support</h3>
|
|
58
|
+
<p>The <a href="#">Skills for Growth</a> service can offer skills advice to businesses with fewer than 250 employees.</p>
|
|
59
|
+
<p>Businesses of any size can get skills advice by completing a <a href="#">skills support request form</a>.</p>
|
|
60
|
+
<p>Businesses of any size can also get skills advice by calling Skills Development Scotland on 0800 783 6000.</p>
|
|
61
|
+
</Tabs.Item>
|
|
62
|
+
],
|
|
63
|
+
title: 'My tabs'
|
|
64
|
+
}
|
|
65
|
+
} satisfies Meta<typeof Tabs>;
|
|
66
|
+
|
|
67
|
+
export default meta;
|
|
68
|
+
type Story = StoryObj<typeof meta>;
|
|
69
|
+
|
|
70
|
+
export const Default: Story = {
|
|
71
|
+
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const ManualActivation: Story = {
|
|
75
|
+
args: {
|
|
76
|
+
isManual: true
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const NoBorder: Story = {
|
|
81
|
+
args: {
|
|
82
|
+
isBorderless: true
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const DifferentHeadingLevel: Story = {
|
|
87
|
+
args: {
|
|
88
|
+
headingLevel: 'h4'
|
|
89
|
+
}
|
|
90
|
+
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { test, expect } from 'vitest';
|
|
2
2
|
import { render, screen, within } from '@testing-library/react';
|
|
3
3
|
import Tabs from './Tabs';
|
|
4
|
-
import slugify from '../../utils/slugify';
|
|
5
4
|
|
|
6
5
|
test('tab container renders correctly', () => {
|
|
7
6
|
render(
|
|
@@ -62,13 +61,12 @@ test('tab container renders correctly', () => {
|
|
|
62
61
|
//expect(tabPanelOne.tabIndex).toEqual(0);
|
|
63
62
|
|
|
64
63
|
// tab panels have ID
|
|
65
|
-
expect(tabPanelOne).
|
|
66
|
-
expect(tabPanelTwo).toHaveAttribute('id');
|
|
64
|
+
expect(tabPanelOne.id).not.toEqual(tabPanelTwo.id);
|
|
67
65
|
});
|
|
68
66
|
|
|
69
67
|
test('non-bordered tabs', () => {
|
|
70
68
|
render(
|
|
71
|
-
<Tabs data-testid="tabcontainer"
|
|
69
|
+
<Tabs data-testid="tabcontainer" isBorderless>
|
|
72
70
|
<Tabs.Item tabLabel="Tab 1" data-testid="tabpanel1">
|
|
73
71
|
<div data-testid="tabpanel1content">Content one</div>
|
|
74
72
|
</Tabs.Item>
|
|
@@ -146,8 +144,8 @@ test('custom baseID', () => {
|
|
|
146
144
|
// default title slugified to part of the ID
|
|
147
145
|
expect(tabHeading).toHaveAttribute('id', `${BASE_ID}-heading`);
|
|
148
146
|
// generated IDs using the slug of the tab title
|
|
149
|
-
expect(tabPanelOne).
|
|
150
|
-
expect(tabPanelTwo).
|
|
147
|
+
expect(tabPanelOne.id.indexOf(BASE_ID)).toBeGreaterThan(-1);
|
|
148
|
+
expect(tabPanelTwo.id.indexOf(BASE_ID)).toBeGreaterThan(-1);
|
|
151
149
|
});
|
|
152
150
|
|
|
153
151
|
test('tab with and without specific ID attribute', () => {
|
|
@@ -169,13 +167,13 @@ test('tab with and without specific ID attribute', () => {
|
|
|
169
167
|
const tabPanelOne = screen.getByTestId('tabpanel1');
|
|
170
168
|
const tabPanelTwo = screen.getByTestId('tabpanel2');
|
|
171
169
|
|
|
172
|
-
expect(tabPanelOne).toHaveAttribute('id'
|
|
170
|
+
expect(tabPanelOne).toHaveAttribute('id');
|
|
173
171
|
expect(tabPanelTwo).toHaveAttribute('id', TAB_ID);
|
|
174
172
|
});
|
|
175
173
|
|
|
176
174
|
test('with manual activation', () => {
|
|
177
175
|
render(
|
|
178
|
-
<Tabs data-testid="tabcontainer"
|
|
176
|
+
<Tabs data-testid="tabcontainer" isManual>
|
|
179
177
|
<Tabs.Item title="Tab 1" data-testid="tabpanel1">
|
|
180
178
|
<div data-testid="tabpanel1content">Content one</div>
|
|
181
179
|
</Tabs.Item>
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import React, { Children, useEffect, useRef } from 'react';
|
|
1
|
+
import React, { Children, useEffect, useRef, useId } from 'react';
|
|
2
2
|
import WrapperTag from '../../common/WrapperTag';
|
|
3
3
|
// @ts-ignore
|
|
4
4
|
import DSTabs from '@scottish-government/design-system/src/components/tabs/tabs';
|
|
5
|
-
import slugify from '../../utils/slugify';
|
|
6
5
|
|
|
7
6
|
const TabItem = ({
|
|
8
|
-
|
|
7
|
+
isBorderless,
|
|
9
8
|
children,
|
|
10
9
|
className,
|
|
11
10
|
id,
|
|
@@ -16,7 +15,7 @@ const TabItem = ({
|
|
|
16
15
|
<div
|
|
17
16
|
className={[
|
|
18
17
|
'ds_tabs__content',
|
|
19
|
-
|
|
18
|
+
!isBorderless && 'ds_tabs__content--bordered',
|
|
20
19
|
className
|
|
21
20
|
].join(' ')}
|
|
22
21
|
id={id}
|
|
@@ -40,11 +39,11 @@ const TabListItem = ({
|
|
|
40
39
|
|
|
41
40
|
const Tabs = ({
|
|
42
41
|
baseId = 'tabs',
|
|
43
|
-
bordered = true,
|
|
44
42
|
children,
|
|
45
43
|
className,
|
|
46
44
|
headingLevel = 'h2',
|
|
47
|
-
|
|
45
|
+
isBorderless,
|
|
46
|
+
isManual = false,
|
|
48
47
|
title = 'Contents',
|
|
49
48
|
...props
|
|
50
49
|
}: SGDS.Component.Tabs) => {
|
|
@@ -63,8 +62,8 @@ const Tabs = ({
|
|
|
63
62
|
|
|
64
63
|
if (thisChild && thisChild.type === TabItem) {
|
|
65
64
|
return React.cloneElement(thisChild, {
|
|
66
|
-
|
|
67
|
-
id: thisChild.props.id || `${baseId}-${
|
|
65
|
+
isBorderless: !!isBorderless,
|
|
66
|
+
id: thisChild.props.id || `${baseId}-${useId()}`,
|
|
68
67
|
});
|
|
69
68
|
}
|
|
70
69
|
});
|
|
@@ -79,7 +78,7 @@ const Tabs = ({
|
|
|
79
78
|
<div
|
|
80
79
|
className={[
|
|
81
80
|
'ds_tabs',
|
|
82
|
-
|
|
81
|
+
isManual && 'ds_tabs--manual',
|
|
83
82
|
className
|
|
84
83
|
].join(' ')}
|
|
85
84
|
ref={ref}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
import Tag from './Tag';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Components/Tag',
|
|
7
|
+
component: Tag,
|
|
8
|
+
argTypes: {
|
|
9
|
+
colour: {
|
|
10
|
+
control: { type: 'select' },
|
|
11
|
+
description: 'The tag colour to use',
|
|
12
|
+
options: ['', 'blue', 'green', 'grey', 'orange', 'pink', 'purple', 'red', 'teal', 'yellow'],
|
|
13
|
+
type: 'string'
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
} satisfies Meta<typeof Tag>;
|
|
17
|
+
|
|
18
|
+
export default meta;
|
|
19
|
+
type Story = StoryObj<typeof meta>;
|
|
20
|
+
|
|
21
|
+
export const Default: Story = {
|
|
22
|
+
args: {
|
|
23
|
+
children: 'Status',
|
|
24
|
+
},
|
|
25
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import TaskList from './TaskList';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/Task list',
|
|
8
|
+
component: TaskList,
|
|
9
|
+
argTypes: {
|
|
10
|
+
headingId: {
|
|
11
|
+
description: 'ID of the task list\'s heading element',
|
|
12
|
+
type: 'string'
|
|
13
|
+
},
|
|
14
|
+
linkComponent: argTypes.linkComponent(),
|
|
15
|
+
title: {
|
|
16
|
+
description: 'The title of the task list',
|
|
17
|
+
type: {
|
|
18
|
+
name: 'string',
|
|
19
|
+
required: true
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
children: argTypes.children()
|
|
23
|
+
},
|
|
24
|
+
args: {
|
|
25
|
+
title: 'Application incomplete'
|
|
26
|
+
}
|
|
27
|
+
} satisfies Meta<typeof TaskList>;
|
|
28
|
+
|
|
29
|
+
export default meta;
|
|
30
|
+
type Story = StoryObj<typeof meta>;
|
|
31
|
+
|
|
32
|
+
export const Default: Story = {
|
|
33
|
+
render: (args) => (
|
|
34
|
+
<TaskList {...args}>
|
|
35
|
+
<TaskList.Item
|
|
36
|
+
href="#conditions"
|
|
37
|
+
id="task-conditions"
|
|
38
|
+
isComplete
|
|
39
|
+
statusText="Completed"
|
|
40
|
+
title="Conditions"
|
|
41
|
+
>
|
|
42
|
+
Tell us about your conditions, symptoms and any sensory issues you have.
|
|
43
|
+
</TaskList.Item>
|
|
44
|
+
<TaskList.Item
|
|
45
|
+
href="#in-progress"
|
|
46
|
+
id="task-medications"
|
|
47
|
+
statusText="In progress"
|
|
48
|
+
title="Medications"
|
|
49
|
+
>
|
|
50
|
+
Tell us about any medication you need.
|
|
51
|
+
</TaskList.Item>
|
|
52
|
+
<TaskList.Item
|
|
53
|
+
id="task-contacts"
|
|
54
|
+
statusText="Cannot start yet"
|
|
55
|
+
title="Contacts and supporting information"
|
|
56
|
+
>
|
|
57
|
+
Share any supporting documents and provide details of people we can talk to about you.
|
|
58
|
+
</TaskList.Item>
|
|
59
|
+
</TaskList>
|
|
60
|
+
)
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const Groups: Story = {
|
|
64
|
+
render: (args) => (
|
|
65
|
+
<TaskList {...args}>
|
|
66
|
+
<TaskList.Group title="Provide your health details">
|
|
67
|
+
<TaskList.Item
|
|
68
|
+
href="#conditions"
|
|
69
|
+
id="task-conditions"
|
|
70
|
+
isComplete
|
|
71
|
+
statusText="Completed"
|
|
72
|
+
title="Conditions"
|
|
73
|
+
>
|
|
74
|
+
Tell us about your conditions, symptoms and any sensory issues you have.
|
|
75
|
+
</TaskList.Item>
|
|
76
|
+
<TaskList.Item
|
|
77
|
+
href="#in-progress"
|
|
78
|
+
id="task-medications"
|
|
79
|
+
isComplete
|
|
80
|
+
statusText="Completed"
|
|
81
|
+
title="Medications"
|
|
82
|
+
>
|
|
83
|
+
Tell us about any medication you need.
|
|
84
|
+
</TaskList.Item>
|
|
85
|
+
<TaskList.Item
|
|
86
|
+
href="#contacts"
|
|
87
|
+
id="task-contacts"
|
|
88
|
+
isComplete
|
|
89
|
+
statusText="Completed"
|
|
90
|
+
title="Contacts and supporting information"
|
|
91
|
+
>
|
|
92
|
+
Share any supporting documents and provide details of people we can talk to about you.
|
|
93
|
+
</TaskList.Item>
|
|
94
|
+
</TaskList.Group>
|
|
95
|
+
<TaskList.Group
|
|
96
|
+
intro="This information will be used to check what additional benefits you may be able to apply for."
|
|
97
|
+
title="Tell us about your daily living and mobility circumstances"
|
|
98
|
+
>
|
|
99
|
+
<TaskList.Item
|
|
100
|
+
href="#preparing-food"
|
|
101
|
+
id="task-preparing-food"
|
|
102
|
+
statusText="In progress"
|
|
103
|
+
tagColour="grey"
|
|
104
|
+
title="Preparing food"
|
|
105
|
+
>
|
|
106
|
+
Questions about your ability to prepare a simple meal safely and any help you need to do this.
|
|
107
|
+
</TaskList.Item>
|
|
108
|
+
<TaskList.Item
|
|
109
|
+
href="#taking-nutrition"
|
|
110
|
+
id="task-taking-nutrition"
|
|
111
|
+
statusText="Not started"
|
|
112
|
+
tagColour="grey"
|
|
113
|
+
title="Taking nutrition"
|
|
114
|
+
>
|
|
115
|
+
Questions about your ability to eat and drink and any help you need to do this.
|
|
116
|
+
</TaskList.Item>
|
|
117
|
+
<TaskList.Item
|
|
118
|
+
href="#managing-therapy"
|
|
119
|
+
id="task-managing-therapy"
|
|
120
|
+
statusText="Not started"
|
|
121
|
+
tagColour="grey"
|
|
122
|
+
title="Managing therapy or monitoring a health condition"
|
|
123
|
+
>
|
|
124
|
+
Questions about any help you need to monitor changes in your health condition, take medication or do therapy at home.
|
|
125
|
+
</TaskList.Item>
|
|
126
|
+
</TaskList.Group>
|
|
127
|
+
</TaskList>
|
|
128
|
+
)
|
|
129
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import argTypes from '../../../.storybook/sgdsArgTypes';
|
|
3
|
+
|
|
4
|
+
import TextInput from './TextInput';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/Text input',
|
|
8
|
+
component: TextInput,
|
|
9
|
+
argTypes: {
|
|
10
|
+
buttonIcon: {
|
|
11
|
+
control: { type: 'select' },
|
|
12
|
+
description: 'Name of the icon to use',
|
|
13
|
+
options: ['ArrowUpward', 'CalendarToday', 'Cancel', 'CheckCircle', 'ChevronLeft', 'ChevronRight', 'Close', 'Description', 'DoubleChevronLeft', 'DoubleChevronRight', 'Error', 'ExpandLess', 'ExpandMore', 'List', 'Menu', 'PriorityHigh', 'Search'],
|
|
14
|
+
type: 'string'
|
|
15
|
+
},
|
|
16
|
+
buttonText: {
|
|
17
|
+
desctiption: 'Text content for the button',
|
|
18
|
+
type: 'string'
|
|
19
|
+
},
|
|
20
|
+
countThreshold: argTypes.countThreshold(),
|
|
21
|
+
currencySymbol: {
|
|
22
|
+
description: 'Currency symbol to use (default is \'£\')',
|
|
23
|
+
type: 'string'
|
|
24
|
+
},
|
|
25
|
+
errorMessage: argTypes.errorMessage(),
|
|
26
|
+
hasButton: {
|
|
27
|
+
control: 'boolean',
|
|
28
|
+
description: 'Whether the component has an associated button',
|
|
29
|
+
type: 'boolean'
|
|
30
|
+
},
|
|
31
|
+
isCurrency: {
|
|
32
|
+
control: 'boolean',
|
|
33
|
+
description: 'Whether the component is a currency field',
|
|
34
|
+
type: 'boolean'
|
|
35
|
+
},
|
|
36
|
+
hasError: argTypes.hasError(),
|
|
37
|
+
hintText: argTypes.hintText(),
|
|
38
|
+
id: argTypes.id(),
|
|
39
|
+
label: argTypes.label(),
|
|
40
|
+
maxlength: argTypes.maxlength(),
|
|
41
|
+
name: {type: 'string'},
|
|
42
|
+
onBlur: argTypes.onBlur(),
|
|
43
|
+
onChange: argTypes.onChange(),
|
|
44
|
+
placeholder: {type: 'string'},
|
|
45
|
+
type: {
|
|
46
|
+
control: { type: 'select' },
|
|
47
|
+
options: ['date', 'datetime-local', 'email', 'month', 'number', 'password', 'search', 'tel', 'text', 'time', 'url', 'week'],
|
|
48
|
+
type: {
|
|
49
|
+
required: true,
|
|
50
|
+
name: 'string'
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
value: {type: 'string'},
|
|
54
|
+
width: argTypes.inputWidth()
|
|
55
|
+
},
|
|
56
|
+
args: {
|
|
57
|
+
id: 'first-name',
|
|
58
|
+
label: 'First name'
|
|
59
|
+
}
|
|
60
|
+
} satisfies Meta<typeof TextInput>;
|
|
61
|
+
|
|
62
|
+
export default meta;
|
|
63
|
+
type Story = StoryObj<typeof meta>;
|
|
64
|
+
|
|
65
|
+
export const Default: Story = {
|
|
66
|
+
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const KitchenSink: Story = {
|
|
70
|
+
args: {
|
|
71
|
+
countThreshold: 50,
|
|
72
|
+
errorMessage: 'This field is required',
|
|
73
|
+
hasError: true,
|
|
74
|
+
hintText: 'Please enter your first or given name',
|
|
75
|
+
id: 'kitchensink',
|
|
76
|
+
maxlength: 20,
|
|
77
|
+
value: 'Cholmondley',
|
|
78
|
+
width: 'fixed-20'
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const Currency: Story = {
|
|
83
|
+
args: {
|
|
84
|
+
currencySymbol: '$',
|
|
85
|
+
id: 'price',
|
|
86
|
+
isCurrency: true,
|
|
87
|
+
label: 'Price per unit',
|
|
88
|
+
placeholder: '0.00',
|
|
89
|
+
step: '.01',
|
|
90
|
+
type: 'number',
|
|
91
|
+
width: 'fluid-one-quarter'
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const WithButton: Story = {
|
|
96
|
+
args: {
|
|
97
|
+
buttonIcon: 'Search',
|
|
98
|
+
buttonText: 'Search',
|
|
99
|
+
hasButton: true,
|
|
100
|
+
id: 'withbutton'
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const Blur: Story = {
|
|
105
|
+
args: {
|
|
106
|
+
onBlur: () => {console.log('text input blur')}
|
|
107
|
+
},
|
|
108
|
+
play: async ({ canvas, userEvent }) => {
|
|
109
|
+
await userEvent.click(canvas.getByRole('textbox'));
|
|
110
|
+
await userEvent.tab();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export const Change: Story = {
|
|
115
|
+
args: {
|
|
116
|
+
onChange: () => {console.log('text input change')}
|
|
117
|
+
},
|
|
118
|
+
play: async ({ canvas, userEvent }) => {
|
|
119
|
+
await userEvent.click(canvas.getByRole('textbox'));
|
|
120
|
+
await userEvent.type(canvas.getByRole('textbox'),'banana');
|
|
121
|
+
await userEvent.tab();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -101,7 +101,7 @@ test('text input with currency', () => {
|
|
|
101
101
|
<TextInput
|
|
102
102
|
id={INPUT_ID}
|
|
103
103
|
label={LABEL_TEXT}
|
|
104
|
-
|
|
104
|
+
isCurrency
|
|
105
105
|
/>
|
|
106
106
|
);
|
|
107
107
|
|
|
@@ -120,8 +120,8 @@ test('text input with custom currency symbol', () => {
|
|
|
120
120
|
<TextInput
|
|
121
121
|
id={INPUT_ID}
|
|
122
122
|
label={LABEL_TEXT}
|
|
123
|
-
currency
|
|
124
123
|
currencySymbol={CURRENCY_SYMBOL}
|
|
124
|
+
isCurrency
|
|
125
125
|
/>
|
|
126
126
|
);
|
|
127
127
|
|
|
@@ -13,7 +13,7 @@ const TextInput = ({
|
|
|
13
13
|
className,
|
|
14
14
|
countThreshold,
|
|
15
15
|
width,
|
|
16
|
-
|
|
16
|
+
isCurrency,
|
|
17
17
|
currencySymbol,
|
|
18
18
|
errorMessage,
|
|
19
19
|
hasButton = false,
|
|
@@ -33,7 +33,7 @@ const TextInput = ({
|
|
|
33
33
|
const errorMessageId = `error-message-${id}`;
|
|
34
34
|
const hintTextId = `hint-text-${id}`;
|
|
35
35
|
const ref = useRef(null);
|
|
36
|
-
const inputWrapperClasses = `${hasButton ? 'ds_input__wrapper ds_input__wrapper--has-icon' : ''} ${
|
|
36
|
+
const inputWrapperClasses = `${hasButton ? 'ds_input__wrapper ds_input__wrapper--has-icon' : ''} ${isCurrency ? 'ds_currency-wrapper' : ''}`;
|
|
37
37
|
const describedbys: string[] = [];
|
|
38
38
|
|
|
39
39
|
if (hintText) { describedbys.push(hintTextId) };
|
|
@@ -64,9 +64,9 @@ const TextInput = ({
|
|
|
64
64
|
>
|
|
65
65
|
<label className="ds_label" htmlFor={id}>{label}</label>
|
|
66
66
|
{hintText && <HintText id={hintTextId} text={hintText} />}
|
|
67
|
-
{errorMessage && <ErrorMessage id={errorMessageId}
|
|
67
|
+
{errorMessage && <ErrorMessage id={errorMessageId}>{errorMessage}</ErrorMessage>}
|
|
68
68
|
<ConditionalWrapper
|
|
69
|
-
condition={hasButton || typeof
|
|
69
|
+
condition={hasButton || typeof isCurrency !== 'undefined' && isCurrency}
|
|
70
70
|
wrapper={(children: React.JSX.Element) => <div className={inputWrapperClasses} data-symbol={currencySymbol}>{children}</div>}
|
|
71
71
|
>
|
|
72
72
|
<input
|
|
@@ -88,7 +88,7 @@ const TextInput = ({
|
|
|
88
88
|
type={type}
|
|
89
89
|
{...props}
|
|
90
90
|
/>
|
|
91
|
-
{hasButton && (buttonText || buttonIcon) && <Button
|
|
91
|
+
{hasButton && (buttonText || buttonIcon) && <Button isIconOnly icon={buttonIcon}>{buttonText}</Button>}
|
|
92
92
|
</ConditionalWrapper>
|
|
93
93
|
</ConditionalWrapper>
|
|
94
94
|
);
|