@scottish-government/designsystem-react 0.7.1 → 0.8.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/@types/common/AbstractNotificationBanner.d.ts +2 -2
- package/@types/common/ActionLink.d.ts +8 -0
- package/@types/common/FileIcon.d.ts +1 -1
- package/@types/common/Icon.d.ts +1 -1
- package/@types/components/Breadcrumbs.d.ts +2 -5
- package/@types/components/Checkbox.d.ts +0 -2
- package/@types/components/ConfirmationMessage.d.ts +1 -1
- package/@types/components/ContentsNav.d.ts +4 -6
- package/@types/components/DatePicker.d.ts +1 -1
- package/@types/components/ErrorSummary.d.ts +3 -4
- package/@types/components/NotificationPanel.d.ts +1 -1
- package/@types/components/Pagination.d.ts +5 -4
- package/@types/components/PhaseBanner.d.ts +0 -1
- package/@types/components/Question.d.ts +1 -1
- package/@types/components/RadioButton.d.ts +0 -1
- package/@types/components/Select.d.ts +0 -7
- package/@types/components/SequentialNavigation.d.ts +4 -4
- package/@types/components/SideNavigation.d.ts +4 -5
- package/@types/components/SiteFooter.d.ts +25 -0
- package/@types/components/SiteHeader.d.ts +10 -3
- package/@types/components/SiteNavigation.d.ts +2 -3
- package/@types/components/SkipLinks.d.ts +3 -4
- package/@types/components/SummaryCard.d.ts +0 -2
- package/@types/components/SummaryList.d.ts +0 -13
- package/@types/components/Tabs.d.ts +0 -1
- package/@types/components/Tag.d.ts +1 -3
- package/@types/components/TaskList.d.ts +1 -0
- package/@types/sgds.d.ts +13 -2
- package/CHANGELOG.md +63 -1
- package/dist/common/AbstractNotificationBanner.jsx +8 -6
- package/dist/common/ActionLink.jsx +19 -0
- package/dist/common/FileIcon.jsx +2 -7
- package/dist/common/Icon.jsx +3 -9
- package/dist/components/Accordion/Accordion.jsx +2 -2
- package/dist/components/Breadcrumbs/Breadcrumbs.jsx +20 -15
- package/dist/components/Checkbox/Checkbox.jsx +2 -30
- package/dist/components/Checkbox/CheckboxGroup.jsx +69 -0
- package/dist/components/ContentsNav/ContentsNav.jsx +27 -16
- package/dist/components/CookieBanner/CookieBanner.jsx +1 -0
- package/dist/components/DatePicker/DatePicker.jsx +5 -5
- package/dist/components/ErrorSummary/ErrorSummary.jsx +28 -18
- package/dist/components/NotificationBanner/NotificationBanner.jsx +2 -2
- package/dist/components/Pagination/Pagination.jsx +42 -22
- package/dist/components/PhaseBanner/PhaseBanner.jsx +3 -3
- package/dist/components/Question/Question.jsx +3 -3
- package/dist/components/RadioButton/RadioButton.jsx +3 -17
- package/dist/components/RadioButton/RadioGroup.jsx +61 -0
- package/dist/components/Select/Select.jsx +4 -7
- package/dist/components/SequentialNavigation/SequentialNavigation.jsx +31 -18
- package/dist/components/SideNavigation/SideNavigation.jsx +17 -16
- package/dist/components/SiteFooter/SiteFooter.jsx +104 -0
- package/dist/components/SiteHeader/SiteHeader.jsx +113 -32
- package/dist/components/SiteNavigation/SiteNavigation.jsx +20 -7
- package/dist/components/SkipLinks/SkipLinks.jsx +10 -10
- package/dist/components/SummaryCard/SummaryCard.jsx +25 -14
- package/dist/components/SummaryList/SummaryList.jsx +65 -47
- package/dist/components/Tabs/Tabs.jsx +6 -6
- package/dist/components/Tag/Tag.jsx +2 -2
- package/dist/components/TaskList/TaskList.jsx +14 -3
- package/dist/components/TextInput/TextInput.jsx +3 -3
- package/dist/components/Textarea/Textarea.jsx +3 -3
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/common/AbstractNotificationBanner.test.tsx +1 -1
- package/src/common/AbstractNotificationBanner.tsx +14 -13
- package/src/common/ActionLink.test.tsx +80 -0
- package/src/common/ActionLink.tsx +27 -0
- package/src/common/ConditionalWrapper.tsx +1 -1
- package/src/common/FileIcon.tsx +7 -11
- package/src/common/HintText.tsx +2 -2
- package/src/common/Icon.tsx +13 -17
- package/src/common/ScreenReaderText.tsx +2 -2
- package/src/common/WrapperTag.tsx +2 -2
- package/src/components/Accordion/Accordion.test.tsx +1 -1
- package/src/components/Accordion/Accordion.tsx +6 -7
- package/src/components/AspectBox/AspectBox.tsx +2 -2
- package/src/components/BackToTop/BackToTop.tsx +2 -2
- package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +79 -47
- package/src/components/Breadcrumbs/Breadcrumbs.tsx +31 -31
- package/src/components/Button/Button.tsx +2 -2
- package/src/components/Checkbox/Checkbox.test.tsx +1 -96
- package/src/components/Checkbox/Checkbox.tsx +3 -55
- package/src/components/Checkbox/CheckboxGroup.test.tsx +37 -0
- package/src/components/Checkbox/CheckboxGroup.tsx +46 -0
- package/src/components/ConfirmationMessage/ConfirmationMessage.tsx +2 -2
- package/src/components/ContentsNav/ContentsNav.test.tsx +40 -51
- package/src/components/ContentsNav/ContentsNav.tsx +32 -25
- package/src/components/CookieBanner/CookieBanner.tsx +3 -3
- package/src/components/DatePicker/DatePicker.test.tsx +1 -1
- package/src/components/DatePicker/DatePicker.tsx +7 -7
- package/src/components/Details/Details.tsx +2 -2
- package/src/components/ErrorMessage/ErrorMessage.tsx +2 -2
- package/src/components/ErrorSummary/ErrorSummary.test.tsx +40 -34
- package/src/components/ErrorSummary/ErrorSummary.tsx +40 -32
- package/src/components/FileDownload/FileDownload.tsx +2 -2
- package/src/components/HideThisPage/HideThisPage.tsx +2 -2
- package/src/components/InsetText/InsetText.tsx +2 -2
- package/src/components/NotificationBanner/NotificationBanner.tsx +6 -7
- package/src/components/NotificationPanel/NotificationPanel.tsx +2 -2
- package/src/components/PageHeader/PageHeader.tsx +2 -2
- package/src/components/PageMetadata/PageMetadata.tsx +4 -5
- package/src/components/Pagination/Pagination.test.tsx +26 -7
- package/src/components/Pagination/Pagination.tsx +70 -36
- package/src/components/PhaseBanner/PhaseBanner.tsx +4 -5
- package/src/components/Question/Question.test.tsx +1 -1
- package/src/components/Question/Question.tsx +5 -5
- package/src/components/RadioButton/RadioButton.test.tsx +7 -126
- package/src/components/RadioButton/RadioButton.tsx +4 -41
- package/src/components/RadioButton/RadioGroup.test.tsx +65 -0
- package/src/components/RadioButton/RadioGroup.tsx +38 -0
- package/src/components/Select/Select.test.tsx +39 -37
- package/src/components/Select/Select.tsx +7 -22
- package/src/components/SequentialNavigation/SequentialNavigation.test.tsx +32 -21
- package/src/components/SequentialNavigation/SequentialNavigation.tsx +52 -30
- package/src/components/SideNavigation/SideNavigation.test.tsx +39 -85
- package/src/components/SideNavigation/SideNavigation.tsx +27 -29
- package/src/components/SiteFooter/SiteFooter.test.tsx +153 -0
- package/src/components/SiteFooter/SiteFooter.tsx +107 -0
- package/src/components/SiteHeader/SiteHeader.test.tsx +87 -79
- package/src/components/SiteHeader/SiteHeader.tsx +103 -40
- package/src/components/SiteNavigation/SiteNavigation.test.tsx +42 -23
- package/src/components/SiteNavigation/SiteNavigation.tsx +28 -16
- package/src/components/SiteSearch/SiteSearch.tsx +2 -2
- package/src/components/SkipLinks/SkipLinks.test.tsx +22 -10
- package/src/components/SkipLinks/SkipLinks.tsx +16 -15
- package/src/components/SummaryCard/SummaryCard.test.tsx +31 -35
- package/src/components/SummaryCard/SummaryCard.tsx +39 -28
- package/src/components/SummaryList/SummaryList.test.tsx +49 -148
- package/src/components/SummaryList/SummaryList.tsx +54 -92
- package/src/components/Table/Table.tsx +2 -2
- package/src/components/Tabs/Tabs.tsx +14 -15
- package/src/components/Tag/Tag.test.tsx +4 -4
- package/src/components/Tag/Tag.tsx +4 -4
- package/src/components/TaskList/TaskList.test.tsx +26 -0
- package/src/components/TaskList/TaskList.tsx +21 -11
- package/src/components/TextInput/TextInput.test.tsx +1 -1
- package/src/components/TextInput/TextInput.tsx +5 -5
- package/src/components/Textarea/Textarea.test.tsx +1 -1
- package/src/components/Textarea/Textarea.tsx +5 -5
- package/src/components/WarningText/WarningText.tsx +2 -2
|
@@ -1,75 +1,6 @@
|
|
|
1
1
|
import { test, expect, vi } from 'vitest';
|
|
2
2
|
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
test('checkbox group renders correct children', () => {
|
|
6
|
-
const ITEMS = [
|
|
7
|
-
{
|
|
8
|
-
id: 'universal-credit',
|
|
9
|
-
label: 'Universal Credit',
|
|
10
|
-
checked: true
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
id: 'pensioncredit',
|
|
14
|
-
label: 'Pension Credit'
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
id: 'jsa',
|
|
18
|
-
label: 'Income-based Job Seeker\'s Allowance',
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
exclusive: true,
|
|
22
|
-
id: 'none',
|
|
23
|
-
label: 'No, I do not receive any of these benefits',
|
|
24
|
-
}
|
|
25
|
-
];
|
|
26
|
-
|
|
27
|
-
render(
|
|
28
|
-
<CheckboxGroup items={ITEMS} />
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
const checkboxes = screen.getAllByRole('checkbox');
|
|
32
|
-
const groupContainer = checkboxes[0].parentElement?.parentElement;
|
|
33
|
-
expect(checkboxes.length).toEqual(ITEMS.length);
|
|
34
|
-
expect(groupContainer).toHaveClass('ds_checkboxes', 'ds_field-group');
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test('checkbox group passes all expected item params', () => {
|
|
38
|
-
const ONBLUR_FUNCTION = vi.fn();
|
|
39
|
-
const ONCHANGE_FUNCTION = vi.fn();
|
|
40
|
-
|
|
41
|
-
render(
|
|
42
|
-
<CheckboxGroup small items={[
|
|
43
|
-
{
|
|
44
|
-
checked: true,
|
|
45
|
-
exclusive: true,
|
|
46
|
-
hintText: 'hint text',
|
|
47
|
-
id: 'myid',
|
|
48
|
-
label: 'label text',
|
|
49
|
-
onBlur: {ONBLUR_FUNCTION},
|
|
50
|
-
onChange: {ONCHANGE_FUNCTION},
|
|
51
|
-
small: true
|
|
52
|
-
}
|
|
53
|
-
]}/>
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
const checkbox = screen.getByRole('checkbox');
|
|
57
|
-
const checkboxContainer = checkbox.parentElement;
|
|
58
|
-
const hintText = screen.getByText('hint text');
|
|
59
|
-
|
|
60
|
-
expect(checkbox).toHaveAttribute('data-behaviour', 'exclusive');
|
|
61
|
-
expect(checkbox).toHaveAttribute('checked');
|
|
62
|
-
expect(checkbox.id).toEqual('myid');
|
|
63
|
-
expect(checkboxContainer).toHaveClass('ds_checkbox--small');
|
|
64
|
-
expect(hintText).toBeInTheDocument();
|
|
65
|
-
expect(checkbox).toHaveAttribute('aria-describedby', hintText.id);
|
|
66
|
-
|
|
67
|
-
// fireEvent.blur(checkbox);
|
|
68
|
-
// expect(ONBLUR_FUNCTION).toHaveBeenCalled();
|
|
69
|
-
|
|
70
|
-
// fireEvent.click(checkbox);
|
|
71
|
-
// expect(ONCHANGE_FUNCTION).toHaveBeenCalled();
|
|
72
|
-
});
|
|
3
|
+
import Checkbox from './Checkbox';
|
|
73
4
|
|
|
74
5
|
test('individual checkbox renders correctly', () => {
|
|
75
6
|
render(
|
|
@@ -165,29 +96,3 @@ test('small checkbox', () => {
|
|
|
165
96
|
|
|
166
97
|
expect(checkboxContainer).toHaveClass('ds_checkbox--small');
|
|
167
98
|
});
|
|
168
|
-
|
|
169
|
-
test('passing additional props', () => {
|
|
170
|
-
render(
|
|
171
|
-
<CheckboxGroup data-test="foo" items={[{
|
|
172
|
-
id: 'universal-credit',
|
|
173
|
-
label: 'Universal Credit'
|
|
174
|
-
}]} />
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
const checkboxes = screen.getAllByRole('checkbox');
|
|
178
|
-
const groupContainer = checkboxes[0]?.parentElement?.parentElement;
|
|
179
|
-
expect(groupContainer?.dataset.test).toEqual('foo');
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
test('passing additional CSS classes', () => {
|
|
183
|
-
render(
|
|
184
|
-
<CheckboxGroup className="foo" items={[{
|
|
185
|
-
id: 'universal-credit',
|
|
186
|
-
label: 'Universal Credit'
|
|
187
|
-
}]} />
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
const checkboxes = screen.getAllByRole('checkbox');
|
|
191
|
-
const groupContainer = checkboxes[0]?.parentElement?.parentElement;
|
|
192
|
-
expect(groupContainer).toHaveClass('foo', 'ds_checkboxes');
|
|
193
|
-
});
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import { useEffect, useRef } from 'react';
|
|
2
|
-
// @ts-ignore
|
|
3
|
-
import DSCheckboxes from '@scottish-government/design-system/src/forms/checkbox/checkboxes'
|
|
4
1
|
import HintText from '../../common/HintText';
|
|
5
2
|
|
|
6
|
-
|
|
3
|
+
const Checkbox = ({
|
|
7
4
|
checked,
|
|
8
5
|
hintText,
|
|
9
6
|
id,
|
|
@@ -13,7 +10,7 @@ export const Checkbox: React.FC<SGDS.Component.Checkbox> = ({
|
|
|
13
10
|
onBlur,
|
|
14
11
|
onChange,
|
|
15
12
|
small
|
|
16
|
-
}) => {
|
|
13
|
+
}: SGDS.Component.Checkbox) => {
|
|
17
14
|
const hintTextId = `hint-text-${id}`;
|
|
18
15
|
const behaviour = exclusive && 'exclusive';
|
|
19
16
|
|
|
@@ -58,55 +55,6 @@ export const Checkbox: React.FC<SGDS.Component.Checkbox> = ({
|
|
|
58
55
|
);
|
|
59
56
|
};
|
|
60
57
|
|
|
61
|
-
/**
|
|
62
|
-
* @param {Object} props - Properties for the element
|
|
63
|
-
* @param {Array} items - Checkboxes
|
|
64
|
-
* @param {boolean} small - Use the small display style for all checkboxes
|
|
65
|
-
* @returns {JSX.Element} - The element
|
|
66
|
-
*/
|
|
67
|
-
export const CheckboxGroup: React.FC<SGDS.Component.Checkbox.Group> = ({
|
|
68
|
-
className,
|
|
69
|
-
items,
|
|
70
|
-
small,
|
|
71
|
-
...props
|
|
72
|
-
}) => {
|
|
73
|
-
const ref = useRef(null);
|
|
74
|
-
|
|
75
|
-
useEffect(() => {
|
|
76
|
-
if (ref.current) {
|
|
77
|
-
new DSCheckboxes(ref.current).init();
|
|
78
|
-
}
|
|
79
|
-
}, [ref]);
|
|
80
|
-
|
|
81
|
-
return (
|
|
82
|
-
<div
|
|
83
|
-
className={[
|
|
84
|
-
'ds_checkboxes',
|
|
85
|
-
'ds_field-group',
|
|
86
|
-
className
|
|
87
|
-
].join(' ')}
|
|
88
|
-
data-module="ds-checkboxes"
|
|
89
|
-
ref={ref}
|
|
90
|
-
{...props}
|
|
91
|
-
>
|
|
92
|
-
{items && items.map((item, index: number) => (
|
|
93
|
-
<Checkbox
|
|
94
|
-
exclusive={item.exclusive}
|
|
95
|
-
checked={item.checked}
|
|
96
|
-
hintText={item.hintText}
|
|
97
|
-
id={item.id}
|
|
98
|
-
key={'checkbox' + index}
|
|
99
|
-
label={item.label}
|
|
100
|
-
onBlur={item.onBlur}
|
|
101
|
-
onChange={item.onChange}
|
|
102
|
-
small={small || item.small}
|
|
103
|
-
/>
|
|
104
|
-
))}
|
|
105
|
-
</div>
|
|
106
|
-
)
|
|
107
|
-
};
|
|
108
|
-
|
|
109
58
|
Checkbox.displayName = 'Checkbox';
|
|
110
|
-
CheckboxGroup.displayName = 'CheckboxGroup';
|
|
111
59
|
|
|
112
|
-
export default
|
|
60
|
+
export default Checkbox;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { test, expect } from 'vitest';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import Checkbox from './Checkbox';
|
|
4
|
+
import CheckboxGroup from './CheckboxGroup';
|
|
5
|
+
|
|
6
|
+
test('checkbox group renders correctly', () => {
|
|
7
|
+
render(
|
|
8
|
+
<CheckboxGroup data-testid="checkboxgroup">
|
|
9
|
+
<Checkbox id="banana" label="Banana" />
|
|
10
|
+
Foo
|
|
11
|
+
</CheckboxGroup>
|
|
12
|
+
);
|
|
13
|
+
const checkboxGroup = screen.getByTestId('checkboxgroup');
|
|
14
|
+
expect(checkboxGroup).toHaveClass('ds_checkboxes', 'ds_field-group');
|
|
15
|
+
|
|
16
|
+
const checkbox = screen.getByRole('checkbox');
|
|
17
|
+
const checkboxContainer = checkbox.parentElement;
|
|
18
|
+
expect(checkboxContainer).not.toHaveClass('ds_checkbox--small');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('passing additional props', () => {
|
|
22
|
+
render(
|
|
23
|
+
<CheckboxGroup data-testid="checkboxgroup" data-test="foo" />
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const checkboxGroup = screen.getByTestId('checkboxgroup');
|
|
27
|
+
expect(checkboxGroup?.dataset.test).toEqual('foo');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('passing additional CSS classes', () => {
|
|
31
|
+
render(
|
|
32
|
+
<CheckboxGroup data-testid="checkboxgroup" className="foo" />
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const checkboxGroup = screen.getByTestId('checkboxgroup');
|
|
36
|
+
expect(checkboxGroup).toHaveClass('foo', 'ds_checkboxes');
|
|
37
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React, { Children, useEffect, useRef } from 'react';
|
|
2
|
+
import Checkbox from './Checkbox';
|
|
3
|
+
// @ts-ignore
|
|
4
|
+
import DSCheckboxes from '@scottish-government/design-system/src/forms/checkbox/checkboxes'
|
|
5
|
+
|
|
6
|
+
export const CheckboxGroup = ({
|
|
7
|
+
children,
|
|
8
|
+
className,
|
|
9
|
+
small,
|
|
10
|
+
...props
|
|
11
|
+
}: SGDS.Component.Checkbox.Group) => {
|
|
12
|
+
function processChild(child: any) {
|
|
13
|
+
if (child && child.type === Checkbox) {
|
|
14
|
+
return React.cloneElement(child as React.ReactElement<SGDS.Component.Checkbox>, { small: small });
|
|
15
|
+
} else {
|
|
16
|
+
return child;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const ref = useRef(null);
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (ref.current) {
|
|
24
|
+
new DSCheckboxes(ref.current).init();
|
|
25
|
+
}
|
|
26
|
+
}, [ref]);
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div
|
|
30
|
+
className={[
|
|
31
|
+
'ds_checkboxes',
|
|
32
|
+
'ds_field-group',
|
|
33
|
+
className
|
|
34
|
+
].join(' ')}
|
|
35
|
+
data-module="ds-checkboxes"
|
|
36
|
+
ref={ref}
|
|
37
|
+
{...props}
|
|
38
|
+
>
|
|
39
|
+
{Children.map(children, child => processChild(child))}
|
|
40
|
+
</div>
|
|
41
|
+
)
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
CheckboxGroup.displayName = 'CheckboxGroup';
|
|
45
|
+
|
|
46
|
+
export default CheckboxGroup;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import Icon from '../../common/Icon';
|
|
2
2
|
import WrapperTag from '../../common/WrapperTag';
|
|
3
3
|
|
|
4
|
-
const ConfirmationMessage
|
|
4
|
+
const ConfirmationMessage = ({
|
|
5
5
|
ariaLive = 'polite',
|
|
6
6
|
children,
|
|
7
7
|
className,
|
|
8
8
|
headingLevel = 'h3',
|
|
9
9
|
title,
|
|
10
10
|
...props
|
|
11
|
-
}) => {
|
|
11
|
+
}: SGDS.Component.ConfirmationMessage) => {
|
|
12
12
|
return (
|
|
13
13
|
<div
|
|
14
14
|
aria-live={ariaLive}
|
|
@@ -1,38 +1,20 @@
|
|
|
1
1
|
import { test, expect } from 'vitest';
|
|
2
2
|
import { render, screen, within } from '@testing-library/react';
|
|
3
|
-
import ContentsNav
|
|
3
|
+
import ContentsNav from './ContentsNav';
|
|
4
4
|
|
|
5
5
|
const ITEM_HREF = '#foo';
|
|
6
6
|
const ITEM_TITLE = 'My content';
|
|
7
|
+
const LABEL_TEXT = 'Pages in this guide';
|
|
7
8
|
|
|
8
9
|
test('contents nav renders correctly', () => {
|
|
9
|
-
const ITEMS = [
|
|
10
|
-
{
|
|
11
|
-
title: 'Apply for Blue Badge',
|
|
12
|
-
current: true
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
title: 'Eligibility',
|
|
16
|
-
href: '#2'
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
title: 'Using your Blue Badge',
|
|
20
|
-
href: '#3'
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
title: 'Report a lost, stolen or misuesd Blue Badge',
|
|
24
|
-
href: '#4'
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
title: 'Changing or handing back a Blue Badge',
|
|
28
|
-
href: '#5'
|
|
29
|
-
}
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
const LABEL_TEXT = 'Pages in this guide';
|
|
33
|
-
|
|
34
10
|
render(
|
|
35
|
-
<ContentsNav
|
|
11
|
+
<ContentsNav ariaLabel={LABEL_TEXT}>
|
|
12
|
+
<ContentsNav.Item>Apply for Blue Badge</ContentsNav.Item>
|
|
13
|
+
<ContentsNav.Item href="#1">Eligibility</ContentsNav.Item>
|
|
14
|
+
<ContentsNav.Item href="#2">Using your Blue Badge</ContentsNav.Item>
|
|
15
|
+
<ContentsNav.Item href="#3">Report a lost, stolen or misuesd Blue Badge</ContentsNav.Item>
|
|
16
|
+
<ContentsNav.Item href="#4">Changing or handing back a Blue Badge</ContentsNav.Item>
|
|
17
|
+
</ContentsNav>
|
|
36
18
|
)
|
|
37
19
|
|
|
38
20
|
const contentsNav = screen.getByRole('navigation');
|
|
@@ -46,14 +28,13 @@ test('contents nav renders correctly', () => {
|
|
|
46
28
|
expect(contentsNavTitle.textContent).toEqual('Contents');
|
|
47
29
|
expect(contentsNavList).toHaveClass('ds_contents-nav__list');
|
|
48
30
|
expect(contentsNavList.tagName).toEqual('UL');
|
|
49
|
-
expect(contentsNavList.children.length).toEqual(ITEMS.length);
|
|
50
31
|
});
|
|
51
32
|
|
|
52
33
|
test('contents nav with custom title', () => {
|
|
53
34
|
const TITLE_TEXT = 'My title';
|
|
54
35
|
|
|
55
36
|
render(
|
|
56
|
-
<ContentsNav title={TITLE_TEXT}
|
|
37
|
+
<ContentsNav title={TITLE_TEXT} />
|
|
57
38
|
);
|
|
58
39
|
|
|
59
40
|
const contentsNav = screen.getByRole('navigation');
|
|
@@ -63,7 +44,7 @@ test('contents nav with custom title', () => {
|
|
|
63
44
|
|
|
64
45
|
test('contents nav item', () => {
|
|
65
46
|
render(
|
|
66
|
-
<
|
|
47
|
+
<ContentsNav.Item href={ITEM_HREF}>{ITEM_TITLE}</ContentsNav.Item>
|
|
67
48
|
);
|
|
68
49
|
|
|
69
50
|
const listItem = screen.getByRole('listitem');
|
|
@@ -77,51 +58,63 @@ test('contents nav item', () => {
|
|
|
77
58
|
expect(link).toHaveAttribute('href', ITEM_HREF);
|
|
78
59
|
});
|
|
79
60
|
|
|
80
|
-
test('contents nav
|
|
61
|
+
test('contents nav item without href', () => {
|
|
81
62
|
render(
|
|
82
|
-
<
|
|
63
|
+
<ContentsNav.Item>{ITEM_TITLE}</ContentsNav.Item>
|
|
83
64
|
);
|
|
84
65
|
|
|
85
66
|
const listItem = screen.getByRole('listitem');
|
|
86
67
|
const link = within(listItem).getByText(ITEM_TITLE);
|
|
87
68
|
|
|
88
|
-
expect(listItem.ariaCurrent).toEqual('page');
|
|
89
69
|
expect(link.tagName).toEqual('SPAN');
|
|
90
|
-
expect(link).toHaveClass('ds_current');
|
|
70
|
+
expect(link).not.toHaveClass('ds_current');
|
|
91
71
|
});
|
|
92
72
|
|
|
93
|
-
test('contents nav
|
|
73
|
+
test('current contents nav item with href', () => {
|
|
94
74
|
render(
|
|
95
|
-
<
|
|
75
|
+
<ContentsNav.Item current href={ITEM_HREF}>{ITEM_TITLE}</ContentsNav.Item>
|
|
96
76
|
);
|
|
97
77
|
|
|
98
78
|
const listItem = screen.getByRole('listitem');
|
|
99
79
|
const link = within(listItem).getByText(ITEM_TITLE);
|
|
100
80
|
|
|
101
|
-
expect(
|
|
102
|
-
expect(link.tagName).toEqual('SPAN');
|
|
81
|
+
expect(link.tagName).toEqual('A');
|
|
103
82
|
expect(link).toHaveClass('ds_current');
|
|
104
83
|
});
|
|
105
84
|
|
|
106
|
-
test('contents nav item without href', () => {
|
|
85
|
+
test('current contents nav item without href', () => {
|
|
107
86
|
render(
|
|
108
|
-
<
|
|
87
|
+
<ContentsNav.Item current>{ITEM_TITLE}</ContentsNav.Item>
|
|
109
88
|
);
|
|
110
89
|
|
|
111
90
|
const listItem = screen.getByRole('listitem');
|
|
112
91
|
const link = within(listItem).getByText(ITEM_TITLE);
|
|
113
92
|
|
|
114
93
|
expect(link.tagName).toEqual('SPAN');
|
|
115
|
-
expect(link).
|
|
94
|
+
expect(link).toHaveClass('ds_current');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('contents nav item with custom element', () => {
|
|
98
|
+
render(
|
|
99
|
+
<ContentsNav.Item href="category" linkComponent={
|
|
100
|
+
({ className, ...props }) => (
|
|
101
|
+
<strong role="link" className={className} {...props}/>
|
|
102
|
+
)}>
|
|
103
|
+
{ITEM_TITLE}
|
|
104
|
+
</ContentsNav.Item>
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
const item = screen.getByRole('listitem');
|
|
109
|
+
const link = within(item).queryByRole('link');
|
|
110
|
+
|
|
111
|
+
expect(link?.tagName).toEqual('STRONG');
|
|
112
|
+
expect(link?.textContent).toEqual(ITEM_TITLE);
|
|
116
113
|
});
|
|
117
114
|
|
|
118
115
|
test('passing additional props', () => {
|
|
119
116
|
render(
|
|
120
|
-
<ContentsNav data-test="foo"
|
|
121
|
-
{
|
|
122
|
-
title: 'Apply for Blue Badge',
|
|
123
|
-
}
|
|
124
|
-
]} />
|
|
117
|
+
<ContentsNav data-test="foo"/>
|
|
125
118
|
)
|
|
126
119
|
|
|
127
120
|
const contentsNav = screen.getByRole('navigation');
|
|
@@ -130,11 +123,7 @@ test('passing additional props', () => {
|
|
|
130
123
|
|
|
131
124
|
test('passing additional CSS classes', () => {
|
|
132
125
|
render(
|
|
133
|
-
<ContentsNav className="foo"
|
|
134
|
-
{
|
|
135
|
-
title: 'Apply for Blue Badge',
|
|
136
|
-
}
|
|
137
|
-
]} />
|
|
126
|
+
<ContentsNav className="foo"/>
|
|
138
127
|
)
|
|
139
128
|
|
|
140
129
|
const contentsNav = screen.getByRole('navigation');
|
|
@@ -1,42 +1,48 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const ContentsNavItem = ({
|
|
4
|
+
children,
|
|
4
5
|
current,
|
|
5
6
|
href,
|
|
6
|
-
|
|
7
|
-
}) => {
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
linkComponent
|
|
8
|
+
}: SGDS.Component.ContentsNav.ContentsNavItem) => {
|
|
9
|
+
const classNames = ['ds_contents-nav__link'];
|
|
10
|
+
let ariaCurrent: React.AriaAttributes["aria-current"];
|
|
11
|
+
|
|
12
|
+
if (current) {
|
|
13
|
+
classNames.push('ds_current');
|
|
14
|
+
ariaCurrent = 'page';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function processChildren(children: React.ReactNode) {
|
|
18
|
+
if (linkComponent) {
|
|
19
|
+
return linkComponent({ className: classNames.join(' '), href, children });
|
|
20
|
+
} else if (href) {
|
|
21
|
+
return <a href={href} aria-current={ariaCurrent ? ariaCurrent : undefined} className={classNames.join(' ')}>{children}</a>;
|
|
22
|
+
} else {
|
|
23
|
+
return <span aria-current={ariaCurrent ? ariaCurrent : undefined} className={classNames.join(' ')}>{children}</span>;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
10
26
|
|
|
11
27
|
return (
|
|
12
28
|
<li
|
|
13
|
-
aria-current={current && 'page' || undefined}
|
|
14
29
|
className="ds_contents-nav__item"
|
|
15
30
|
>
|
|
16
|
-
|
|
17
|
-
tagName={tagName}
|
|
18
|
-
className={[
|
|
19
|
-
'ds_contents-nav__link',
|
|
20
|
-
current && 'ds_current'
|
|
21
|
-
].join(' ')}
|
|
22
|
-
href={!current ? href : undefined}
|
|
23
|
-
>
|
|
24
|
-
{title}
|
|
25
|
-
</WrapperTag>
|
|
31
|
+
{processChildren(children)}
|
|
26
32
|
</li>
|
|
27
33
|
);
|
|
28
34
|
};
|
|
29
35
|
|
|
30
|
-
const ContentsNav
|
|
36
|
+
const ContentsNav = ({
|
|
37
|
+
ariaLabel = 'Pages in this section',
|
|
38
|
+
children,
|
|
31
39
|
className,
|
|
32
|
-
items,
|
|
33
|
-
label = 'Pages in this section',
|
|
34
40
|
title = 'Contents',
|
|
35
41
|
...props
|
|
36
|
-
}) {
|
|
42
|
+
}: SGDS.Component.ContentsNav) => {
|
|
37
43
|
return (
|
|
38
44
|
<nav
|
|
39
|
-
aria-label={
|
|
45
|
+
aria-label={ariaLabel}
|
|
40
46
|
className={[
|
|
41
47
|
'ds_contents-nav',
|
|
42
48
|
className
|
|
@@ -44,15 +50,16 @@ const ContentsNav: React.FC<SGDS.Component.ContentsNav> = function ({
|
|
|
44
50
|
{...props}
|
|
45
51
|
>
|
|
46
52
|
<h2 className="ds_contents-nav__title">{title}</h2>
|
|
53
|
+
|
|
47
54
|
<ul className="ds_contents-nav__list">
|
|
48
|
-
{
|
|
49
|
-
<Link current={item.current} href={item.href} title={item.title} key={'link' + index} />
|
|
50
|
-
))}
|
|
55
|
+
{children}
|
|
51
56
|
</ul>
|
|
52
57
|
</nav>
|
|
53
58
|
);
|
|
54
59
|
};
|
|
55
60
|
|
|
56
61
|
ContentsNav.displayName = 'ContentsNav';
|
|
62
|
+
ContentsNavItem.displayName = 'ContentsNav.Item';
|
|
63
|
+
ContentsNav.Item = ContentsNavItem;
|
|
57
64
|
|
|
58
65
|
export default ContentsNav;
|
|
@@ -3,13 +3,12 @@ import AbstractNotificationBanner from '../../common/AbstractNotificationBanner'
|
|
|
3
3
|
// @ts-ignore
|
|
4
4
|
import DSCookieBanner from '@scottish-government/design-system/src/components/cookie-notification/cookie-notification.js';
|
|
5
5
|
|
|
6
|
-
const CookieBanner
|
|
7
|
-
& { Buttons?: React.FC<SGDS.Common.AbstractNotificationBanner.Buttons> } = ({
|
|
6
|
+
const CookieBanner = ({
|
|
8
7
|
children,
|
|
9
8
|
className,
|
|
10
9
|
title,
|
|
11
10
|
...props
|
|
12
|
-
|
|
11
|
+
}: SGDS.Common.AbstractNotificationBanner) => {
|
|
13
12
|
|
|
14
13
|
return (
|
|
15
14
|
<>
|
|
@@ -32,5 +31,6 @@ const CookieBanner: React.FC<SGDS.Common.AbstractNotificationBanner>
|
|
|
32
31
|
|
|
33
32
|
CookieBanner.displayName = 'CookieBanner';
|
|
34
33
|
CookieBanner.Buttons = AbstractNotificationBanner.Buttons;
|
|
34
|
+
CookieBanner.Buttons.displayName = 'CookieBanner.Buttons';
|
|
35
35
|
|
|
36
36
|
export default CookieBanner;
|
|
@@ -4,12 +4,12 @@ import DSDatePicker from '@scottish-government/design-system/src/components/date
|
|
|
4
4
|
import ErrorMessage from '../ErrorMessage/ErrorMessage';
|
|
5
5
|
import TextInput from '../TextInput/TextInput';
|
|
6
6
|
|
|
7
|
-
const DatePicker
|
|
7
|
+
const DatePicker = ({
|
|
8
8
|
className,
|
|
9
9
|
dateSelectCallback,
|
|
10
10
|
disabledDates,
|
|
11
|
-
error,
|
|
12
11
|
errorMessage,
|
|
12
|
+
hasError,
|
|
13
13
|
hintText,
|
|
14
14
|
id,
|
|
15
15
|
iconPath = './',
|
|
@@ -23,7 +23,7 @@ const DatePicker: React.FC<SGDS.Component.DatePicker> = ({
|
|
|
23
23
|
value,
|
|
24
24
|
width = 'fixed-10',
|
|
25
25
|
...props
|
|
26
|
-
}) => {
|
|
26
|
+
}: SGDS.Component.DatePicker) => {
|
|
27
27
|
const ref = useRef(null);
|
|
28
28
|
|
|
29
29
|
useEffect(() => {
|
|
@@ -68,7 +68,7 @@ const DatePicker: React.FC<SGDS.Component.DatePicker> = ({
|
|
|
68
68
|
<div>
|
|
69
69
|
<TextInput
|
|
70
70
|
className="js-datepicker-date"
|
|
71
|
-
|
|
71
|
+
hasError={!!hasError}
|
|
72
72
|
id={id + "-day"}
|
|
73
73
|
hintText={hintText}
|
|
74
74
|
label="Day"
|
|
@@ -83,7 +83,7 @@ const DatePicker: React.FC<SGDS.Component.DatePicker> = ({
|
|
|
83
83
|
<div>
|
|
84
84
|
<TextInput
|
|
85
85
|
className="js-datepicker-month"
|
|
86
|
-
|
|
86
|
+
hasError={!!hasError}
|
|
87
87
|
id={id + "-month"}
|
|
88
88
|
hintText={hintText}
|
|
89
89
|
label="Month"
|
|
@@ -98,7 +98,7 @@ const DatePicker: React.FC<SGDS.Component.DatePicker> = ({
|
|
|
98
98
|
<div>
|
|
99
99
|
<TextInput
|
|
100
100
|
className="js-datepicker-year"
|
|
101
|
-
|
|
101
|
+
hasError={!!hasError}
|
|
102
102
|
id={id + "-year"}
|
|
103
103
|
hintText={hintText}
|
|
104
104
|
label="Year"
|
|
@@ -112,7 +112,7 @@ const DatePicker: React.FC<SGDS.Component.DatePicker> = ({
|
|
|
112
112
|
</fieldset>
|
|
113
113
|
) : (
|
|
114
114
|
<TextInput
|
|
115
|
-
|
|
115
|
+
hasError={!!hasError}
|
|
116
116
|
errorMessage={errorMessage}
|
|
117
117
|
id={id}
|
|
118
118
|
hasButton
|