@scottish-government/designsystem-react 0.7.0 → 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/{aspect-box/aspect-box.jsx → Checkbox/CheckboxGroup.jsx} +19 -29
- 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/{common/icon.jsx → components/RadioButton/RadioGroup.jsx} +22 -18
- 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
- package/dist/common/abstract-notification-banner.jsx +0 -63
- package/dist/common/conditional-wrapper.jsx +0 -8
- package/dist/common/file-icon.jsx +0 -51
- package/dist/common/hint-text.jsx +0 -9
- package/dist/common/screen-reader-text.jsx +0 -9
- package/dist/common/wrapper-tag.jsx +0 -11
- package/dist/components/accordion/accordion.jsx +0 -102
- package/dist/components/back-to-top/back-to-top.jsx +0 -27
- package/dist/components/breadcrumbs/breadcrumbs.jsx +0 -28
- package/dist/components/button/button.jsx +0 -30
- package/dist/components/checkbox/checkbox.jsx +0 -62
- package/dist/components/confirmation-message/confirmation-message.jsx +0 -24
- package/dist/components/contents-nav/contents-nav.jsx +0 -33
- package/dist/components/cookie-banner/cookie-banner.jsx +0 -21
- package/dist/components/date-picker/date-picker.jsx +0 -54
- package/dist/components/details/details.jsx +0 -17
- package/dist/components/error-message/error-message.jsx +0 -12
- package/dist/components/error-summary/error-summary.jsx +0 -27
- package/dist/components/file-download/file-download.jsx +0 -50
- package/dist/components/hide-this-page/hide-this-page.jsx +0 -71
- package/dist/components/inset-text/inset-text.jsx +0 -14
- package/dist/components/notification-banner/notification-banner.jsx +0 -26
- package/dist/components/notification-panel/notification-panel.jsx +0 -21
- package/dist/components/page-header/page-header.jsx +0 -15
- package/dist/components/page-metadata/page-metadata.jsx +0 -26
- package/dist/components/pagination/pagination.jsx +0 -97
- package/dist/components/phase-banner/phase-banner.jsx +0 -23
- package/dist/components/question/question.jsx +0 -22
- package/dist/components/radio-button/radio-button.jsx +0 -43
- package/dist/components/select/select.jsx +0 -52
- package/dist/components/sequential-navigation/sequential-navigation.jsx +0 -31
- package/dist/components/side-navigation/side-navigation.jsx +0 -52
- package/dist/components/site-header/site-header.jsx +0 -68
- package/dist/components/site-navigation/site-navigation.jsx +0 -22
- package/dist/components/site-search/site-search.jsx +0 -55
- package/dist/components/skip-links/skip-links.jsx +0 -21
- package/dist/components/summary-card/summary-card.jsx +0 -67
- package/dist/components/summary-list/summary-list.jsx +0 -75
- package/dist/components/table/table.jsx +0 -24
- package/dist/components/tabs/tabs.jsx +0 -99
- package/dist/components/tag/tag.jsx +0 -13
- package/dist/components/task-list/task-list.jsx +0 -95
- package/dist/components/text-input/text-input.jsx +0 -58
- package/dist/components/textarea/textarea.jsx +0 -54
- package/dist/components/warning-text/warning-text.jsx +0 -16
- package/dist/icons/ArrowUpward.jsx +0 -41
- package/dist/icons/CalendarToday.jsx +0 -41
- package/dist/icons/Cancel.jsx +0 -40
- package/dist/icons/CheckCircle.jsx +0 -41
- package/dist/icons/ChevronLeft.jsx +0 -41
- package/dist/icons/ChevronRight.jsx +0 -41
- package/dist/icons/Close.jsx +0 -41
- package/dist/icons/Description.jsx +0 -41
- package/dist/icons/DoubleChevronLeft.jsx +0 -40
- package/dist/icons/DoubleChevronRight.jsx +0 -40
- package/dist/icons/Error.jsx +0 -41
- package/dist/icons/ExpandLess.jsx +0 -41
- package/dist/icons/ExpandMore.jsx +0 -41
- package/dist/icons/List.jsx +0 -44
- package/dist/icons/Menu.jsx +0 -41
- package/dist/icons/PriorityHigh.jsx +0 -42
- package/dist/icons/Search.jsx +0 -41
- package/dist/icons/index.js +0 -40
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { test, expect, vi } from 'vitest';
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
+
import ActionLink from './ActionLink';
|
|
4
|
+
|
|
5
|
+
const ONCLICK_FUNCTION = vi.fn();
|
|
6
|
+
const ACTION_HREF = "#foo"
|
|
7
|
+
const ACTION_ONCLICK = ONCLICK_FUNCTION;
|
|
8
|
+
const ACTION_TEXT = 'Name';
|
|
9
|
+
const DESCRIBEDBY_ID = 'q1-name';
|
|
10
|
+
|
|
11
|
+
test('button action', () => {
|
|
12
|
+
render(
|
|
13
|
+
<ActionLink
|
|
14
|
+
describedby={DESCRIBEDBY_ID}
|
|
15
|
+
href={undefined}
|
|
16
|
+
onclick={ACTION_ONCLICK}
|
|
17
|
+
>
|
|
18
|
+
{ACTION_TEXT}
|
|
19
|
+
</ActionLink>
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const action = screen.getByRole('button');
|
|
23
|
+
|
|
24
|
+
expect(action).toHaveClass('ds_link');
|
|
25
|
+
expect(action).toHaveAttribute('aria-describedby', DESCRIBEDBY_ID);
|
|
26
|
+
expect(action).toHaveAttribute('type', 'button');
|
|
27
|
+
expect(action).not.toHaveAttribute('href');
|
|
28
|
+
expect(action.tagName).toEqual('BUTTON');
|
|
29
|
+
expect(action.textContent).toEqual(ACTION_TEXT);
|
|
30
|
+
|
|
31
|
+
fireEvent.click(action);
|
|
32
|
+
|
|
33
|
+
expect(ONCLICK_FUNCTION).toHaveBeenCalled();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('link action', () => {
|
|
37
|
+
render(
|
|
38
|
+
<ActionLink
|
|
39
|
+
describedby={DESCRIBEDBY_ID}
|
|
40
|
+
href={ACTION_HREF}
|
|
41
|
+
onclick={ACTION_ONCLICK}
|
|
42
|
+
>
|
|
43
|
+
{ACTION_TEXT}
|
|
44
|
+
</ActionLink >
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const action = screen.getByRole('link');
|
|
48
|
+
|
|
49
|
+
expect(action).toHaveClass('ds_link');
|
|
50
|
+
expect(action).toHaveAttribute('aria-describedby', DESCRIBEDBY_ID);
|
|
51
|
+
expect(action).toHaveAttribute('href', ACTION_HREF);
|
|
52
|
+
expect(action).not.toHaveAttribute('type');
|
|
53
|
+
expect(action.tagName).toEqual('A');
|
|
54
|
+
expect(action.textContent).toEqual(ACTION_TEXT);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('action with custom element', () => {
|
|
58
|
+
render(
|
|
59
|
+
<ActionLink
|
|
60
|
+
describedby={DESCRIBEDBY_ID}
|
|
61
|
+
href={ACTION_HREF}
|
|
62
|
+
onclick={ACTION_ONCLICK}
|
|
63
|
+
linkComponent={
|
|
64
|
+
({ className, ...props }) => (
|
|
65
|
+
<strong role="link" className={className} {...props}/>
|
|
66
|
+
)}>
|
|
67
|
+
{ACTION_TEXT}
|
|
68
|
+
</ActionLink>
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const action = screen.getByRole('link');
|
|
72
|
+
|
|
73
|
+
expect(action).toHaveAttribute('aria-describedby', DESCRIBEDBY_ID);
|
|
74
|
+
expect(action?.tagName).toEqual('STRONG');
|
|
75
|
+
expect(action?.textContent).toEqual(ACTION_TEXT);
|
|
76
|
+
|
|
77
|
+
fireEvent.click(action);
|
|
78
|
+
|
|
79
|
+
expect(ONCLICK_FUNCTION).toHaveBeenCalled();
|
|
80
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const ActionLink = ({
|
|
2
|
+
children,
|
|
3
|
+
describedby,
|
|
4
|
+
href,
|
|
5
|
+
linkComponent,
|
|
6
|
+
onclick
|
|
7
|
+
}: SGDS.Common.ActionLink) => {
|
|
8
|
+
const CLASSNAME = 'ds_link';
|
|
9
|
+
|
|
10
|
+
function processChildren(children: React.ReactNode) {
|
|
11
|
+
if (linkComponent) {
|
|
12
|
+
return linkComponent({ className: CLASSNAME, href, children, onClick: onclick, 'aria-describedby': describedby });
|
|
13
|
+
} else if (href) {
|
|
14
|
+
return <a aria-describedby={describedby} onClick={onclick} href={href} className={CLASSNAME}>{children}</a>;
|
|
15
|
+
} else {
|
|
16
|
+
return <button type="button" aria-describedby={describedby} onClick={onclick} className={CLASSNAME}>{children}</button>;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
processChildren(children)
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
ActionLink.displayName = 'ActionLink';
|
|
26
|
+
|
|
27
|
+
export default ActionLink;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Wraps all children in a specified HTML tag if a condition is met.
|
|
3
3
|
*/
|
|
4
|
-
const ConditionalWrapper
|
|
4
|
+
const ConditionalWrapper = ({ condition, wrapper, children }:SGDS.Common.ConditionalWrapper) =>
|
|
5
5
|
condition ? wrapper(children) : children;
|
|
6
6
|
|
|
7
7
|
ConditionalWrapper.displayName = 'ConditionalWrapper';
|
package/src/common/FileIcon.tsx
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import * as FileIcons from '../images/documents';
|
|
3
3
|
|
|
4
|
-
const FileIcon
|
|
4
|
+
const FileIcon = ({
|
|
5
5
|
ariaLabel = '',
|
|
6
6
|
className,
|
|
7
7
|
icon
|
|
8
|
-
}) => {
|
|
9
|
-
const
|
|
10
|
-
{
|
|
11
|
-
className: className,
|
|
12
|
-
'aria-label': ariaLabel
|
|
13
|
-
}
|
|
14
|
-
);
|
|
8
|
+
}: SGDS.Common.FileIcon) => {
|
|
9
|
+
const FileIconComponent = FileIcons[icon];
|
|
15
10
|
|
|
16
11
|
return (
|
|
17
|
-
|
|
18
|
-
{
|
|
19
|
-
|
|
12
|
+
<FileIconComponent
|
|
13
|
+
aria-label={ariaLabel}
|
|
14
|
+
className={className}
|
|
15
|
+
/>
|
|
20
16
|
);
|
|
21
17
|
};
|
|
22
18
|
|
package/src/common/HintText.tsx
CHANGED
package/src/common/Icon.tsx
CHANGED
|
@@ -1,30 +1,26 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import * as Icons from '../images/icons';
|
|
3
3
|
|
|
4
|
-
const Icon
|
|
4
|
+
const Icon = ({
|
|
5
5
|
ariaLabel,
|
|
6
6
|
className,
|
|
7
7
|
fill,
|
|
8
8
|
icon,
|
|
9
9
|
iconSize
|
|
10
|
-
}) => {
|
|
11
|
-
const
|
|
12
|
-
{
|
|
13
|
-
'aria-hidden': ariaLabel ? undefined : true,
|
|
14
|
-
'aria-label': ariaLabel,
|
|
15
|
-
className: [
|
|
16
|
-
'ds_icon',
|
|
17
|
-
className,
|
|
18
|
-
fill && 'ds_icon--fill',
|
|
19
|
-
iconSize && `ds_icon--${iconSize}`
|
|
20
|
-
].join(' ')
|
|
21
|
-
}
|
|
22
|
-
);
|
|
10
|
+
}: SGDS.Common.Icon) => {
|
|
11
|
+
const IconComponent = Icons[icon];
|
|
23
12
|
|
|
24
13
|
return (
|
|
25
|
-
|
|
26
|
-
{
|
|
27
|
-
|
|
14
|
+
<IconComponent
|
|
15
|
+
aria-hidden={ariaLabel ? undefined : true}
|
|
16
|
+
aria-label={ariaLabel}
|
|
17
|
+
className={[
|
|
18
|
+
'ds_icon',
|
|
19
|
+
className,
|
|
20
|
+
fill && 'ds_icon--fill',
|
|
21
|
+
iconSize && `ds_icon--${iconSize}`
|
|
22
|
+
].join(' ')}
|
|
23
|
+
/>
|
|
28
24
|
);
|
|
29
25
|
};
|
|
30
26
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Wraps all children in a specified HTML tag.
|
|
3
3
|
*/
|
|
4
|
-
const WrapperTag
|
|
4
|
+
const WrapperTag = ({
|
|
5
5
|
children,
|
|
6
6
|
tagName = 'div',
|
|
7
7
|
...props
|
|
8
|
-
}) => {
|
|
8
|
+
}: SGDS.Common.WrapperTag) => {
|
|
9
9
|
const TagName = tagName;
|
|
10
10
|
return <TagName {...props}>{children}</TagName>;
|
|
11
11
|
};
|
|
@@ -216,7 +216,7 @@ test('passing additional props to accordion item', () => {
|
|
|
216
216
|
);
|
|
217
217
|
|
|
218
218
|
const accordionItem = screen.getByTestId(ACCORDION_ITEM_ID);
|
|
219
|
-
expect(accordionItem
|
|
219
|
+
expect(accordionItem.dataset.test).toEqual('foo');
|
|
220
220
|
});
|
|
221
221
|
|
|
222
222
|
test('passing additional CSS classes', () => {
|
|
@@ -5,7 +5,7 @@ import DSAccordion from '@scottish-government/design-system/src/components/accor
|
|
|
5
5
|
|
|
6
6
|
let accordionItemCounter = 0;
|
|
7
7
|
|
|
8
|
-
const AccordionItem
|
|
8
|
+
const AccordionItem = ({
|
|
9
9
|
children,
|
|
10
10
|
className,
|
|
11
11
|
headingLevel = 'h3',
|
|
@@ -13,7 +13,7 @@ const AccordionItem: React.FC<SGDS.Component.Accordion.Item> = ({
|
|
|
13
13
|
open = false,
|
|
14
14
|
title,
|
|
15
15
|
...props
|
|
16
|
-
}) => {
|
|
16
|
+
}: SGDS.Component.Accordion.Item) => {
|
|
17
17
|
accordionItemCounter = accordionItemCounter + 1;
|
|
18
18
|
const processedId = rawId || `accordion-item-${accordionItemCounter}`;
|
|
19
19
|
return (
|
|
@@ -43,7 +43,7 @@ const AccordionItem: React.FC<SGDS.Component.Accordion.Item> = ({
|
|
|
43
43
|
>
|
|
44
44
|
{title}
|
|
45
45
|
</WrapperTag>
|
|
46
|
-
<span className=
|
|
46
|
+
<span className="ds_accordion-item__indicator" />
|
|
47
47
|
<label
|
|
48
48
|
className="ds_accordion-item__label"
|
|
49
49
|
htmlFor={`${processedId}-control`}
|
|
@@ -58,14 +58,13 @@ const AccordionItem: React.FC<SGDS.Component.Accordion.Item> = ({
|
|
|
58
58
|
);
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
-
const Accordion
|
|
62
|
-
& { Item: React.FC<SGDS.Component.Accordion.Item> } = ({
|
|
61
|
+
const Accordion = ({
|
|
63
62
|
children,
|
|
64
63
|
className,
|
|
65
64
|
headingLevel = 'h3',
|
|
66
65
|
hideOpenAll,
|
|
67
66
|
...props
|
|
68
|
-
}) => {
|
|
67
|
+
}: SGDS.Component.Accordion) => {
|
|
69
68
|
const ref = useRef(null);
|
|
70
69
|
|
|
71
70
|
useEffect(() => {
|
|
@@ -112,7 +111,7 @@ const Accordion: React.FC<SGDS.Component.Accordion>
|
|
|
112
111
|
};
|
|
113
112
|
|
|
114
113
|
Accordion.displayName = 'Accordion';
|
|
115
|
-
AccordionItem.displayName = '
|
|
114
|
+
AccordionItem.displayName = 'Accordion.Item';
|
|
116
115
|
Accordion.Item = AccordionItem;
|
|
117
116
|
|
|
118
117
|
export default Accordion;
|
|
@@ -2,12 +2,12 @@ import React, { Children, useEffect, useRef } from 'react';
|
|
|
2
2
|
// @ts-ignore
|
|
3
3
|
import DSAspectBox from '@scottish-government/design-system/src/components/aspect-box/aspect-box-fallback';
|
|
4
4
|
|
|
5
|
-
const AspectBox
|
|
5
|
+
const AspectBox = ({
|
|
6
6
|
children,
|
|
7
7
|
className,
|
|
8
8
|
ratio,
|
|
9
9
|
...props
|
|
10
|
-
}) => {
|
|
10
|
+
}: SGDS.Component.AspectBox) => {
|
|
11
11
|
const ref = useRef(null);
|
|
12
12
|
|
|
13
13
|
useEffect(() => {
|
|
@@ -3,11 +3,11 @@ import Icon from '../../common/Icon';
|
|
|
3
3
|
// @ts-ignore
|
|
4
4
|
import DSBackToTop from '@scottish-government/design-system/src/components/back-to-top/back-to-top';
|
|
5
5
|
|
|
6
|
-
const BackToTop
|
|
6
|
+
const BackToTop = ({
|
|
7
7
|
className,
|
|
8
8
|
href = '#page-top',
|
|
9
9
|
...props
|
|
10
|
-
}) => {
|
|
10
|
+
}: SGDS.Component.BackToTop) => {
|
|
11
11
|
const ref = useRef(null);
|
|
12
12
|
|
|
13
13
|
useEffect(() => {
|
|
@@ -2,15 +2,16 @@ import { test, expect } from 'vitest';
|
|
|
2
2
|
import { render, screen, within } from '@testing-library/react';
|
|
3
3
|
import Breadcrumbs from './Breadcrumbs';
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
{ href: 'category', title: 'Category' },
|
|
8
|
-
{ title: 'Page' }
|
|
9
|
-
];
|
|
5
|
+
const LINK_HREF = '#home';
|
|
6
|
+
const LINK_TEXT = 'Home';
|
|
10
7
|
|
|
11
|
-
test('
|
|
8
|
+
test('breadcrumbs render correctly', () => {
|
|
12
9
|
render(
|
|
13
|
-
<Breadcrumbs
|
|
10
|
+
<Breadcrumbs>
|
|
11
|
+
<Breadcrumbs.Item href="home">Home</Breadcrumbs.Item>
|
|
12
|
+
<Breadcrumbs.Item href="category">Category</Breadcrumbs.Item>
|
|
13
|
+
<Breadcrumbs.Item>Page</Breadcrumbs.Item>
|
|
14
|
+
</Breadcrumbs>
|
|
14
15
|
);
|
|
15
16
|
|
|
16
17
|
const nav = screen.getByRole('navigation');
|
|
@@ -23,67 +24,98 @@ test('renders correctly', () => {
|
|
|
23
24
|
// check list
|
|
24
25
|
expect(list.tagName).toEqual('OL');
|
|
25
26
|
expect(list).toHaveClass('ds_breadcrumbs');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('passing additional props to breadcrumbs', () => {
|
|
30
|
+
render(
|
|
31
|
+
<Breadcrumbs data-test="foo"/>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const nav = screen.getByRole('navigation');
|
|
35
|
+
expect(nav.dataset.test).toEqual('foo');
|
|
36
|
+
});
|
|
26
37
|
|
|
27
|
-
|
|
28
|
-
|
|
38
|
+
test('passing additional CSS classes to breadcrumbs', () => {
|
|
39
|
+
render(
|
|
40
|
+
<Breadcrumbs className="foo"/>
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const nav = screen.getByRole('navigation');
|
|
44
|
+
expect(nav).toHaveClass('foo');
|
|
45
|
+
});
|
|
29
46
|
|
|
30
|
-
|
|
31
|
-
|
|
47
|
+
test('breadcrumb item with link', () => {
|
|
48
|
+
render(
|
|
49
|
+
<Breadcrumbs.Item href={LINK_HREF}>{LINK_TEXT}</Breadcrumbs.Item>
|
|
50
|
+
);
|
|
32
51
|
|
|
33
|
-
|
|
52
|
+
const item = screen.getByRole('listitem');
|
|
53
|
+
const link = within(item).getByRole('link');
|
|
34
54
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
expect(link).toHaveClass('ds_breadcrumbs__link');
|
|
38
|
-
} else {
|
|
39
|
-
expect(link).toBeNull();
|
|
40
|
-
}
|
|
41
|
-
});
|
|
55
|
+
expect(item).toHaveClass('ds_breadcrumbs__item');
|
|
56
|
+
expect(item?.tagName).toEqual('LI');
|
|
42
57
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
expect(
|
|
58
|
+
expect(link).toHaveClass('ds_breadcrumbs__link');
|
|
59
|
+
expect(link).toHaveAttribute('href', LINK_HREF);
|
|
60
|
+
expect(link?.tagName).toEqual('A');
|
|
61
|
+
expect(link?.textContent).toEqual(LINK_TEXT);
|
|
46
62
|
});
|
|
47
63
|
|
|
48
|
-
test('
|
|
64
|
+
test('breadcrumb item without link', () => {
|
|
49
65
|
render(
|
|
50
|
-
<Breadcrumbs
|
|
51
|
-
hideLastItem
|
|
52
|
-
items={ITEMS}
|
|
53
|
-
/>
|
|
66
|
+
<Breadcrumbs.Item>{LINK_TEXT}</Breadcrumbs.Item>
|
|
54
67
|
);
|
|
55
68
|
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
expect(
|
|
69
|
+
const item = screen.getByRole('listitem');
|
|
70
|
+
const link = within(item).queryByRole('link');
|
|
71
|
+
|
|
72
|
+
expect(item).toHaveClass('ds_breadcrumbs__item');
|
|
73
|
+
expect(item?.tagName).toEqual('LI');
|
|
74
|
+
expect(item?.textContent).toEqual(LINK_TEXT);
|
|
60
75
|
|
|
61
|
-
|
|
62
|
-
const pageCrumb = within(list).getByText('Page');
|
|
63
|
-
expect(pageCrumb).toHaveClass('visually-hidden');
|
|
64
|
-
expect(pageCrumb.tagName).toEqual('LI');
|
|
76
|
+
expect(link).not.toBeInTheDocument();
|
|
65
77
|
});
|
|
66
78
|
|
|
67
|
-
test('
|
|
79
|
+
test('hidden breadcrumb item', () => {
|
|
68
80
|
render(
|
|
69
|
-
<Breadcrumbs
|
|
70
|
-
items={ITEMS}
|
|
71
|
-
data-test="foo"
|
|
72
|
-
/>
|
|
81
|
+
<Breadcrumbs.Item data-testid="Breadcrumbs.Item" isHidden>{LINK_TEXT}</Breadcrumbs.Item>
|
|
73
82
|
);
|
|
74
83
|
|
|
75
|
-
const
|
|
84
|
+
const item = screen.getByRole('listitem');
|
|
85
|
+
expect(item).toHaveClass('visually-hidden');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('renders breadcrumb with custom element', () => {
|
|
89
|
+
render(
|
|
90
|
+
<Breadcrumbs.Item href="category" linkComponent={
|
|
91
|
+
({ className, ...props }) => (
|
|
92
|
+
<span role="link" className={className} {...props}/>
|
|
93
|
+
)}>
|
|
94
|
+
{LINK_TEXT}
|
|
95
|
+
</Breadcrumbs.Item>
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
const item = screen.getByRole('listitem');
|
|
99
|
+
const link = within(item).queryByRole('link');
|
|
100
|
+
|
|
101
|
+
expect(link?.tagName).toEqual('SPAN');
|
|
102
|
+
expect(link?.textContent).toEqual(LINK_TEXT);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test('passing additional props to breadcrumb item', () => {
|
|
106
|
+
render(
|
|
107
|
+
<Breadcrumbs.Item data-test="foo"/>
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const nav = screen.getByRole('listitem');
|
|
76
111
|
expect(nav.dataset.test).toEqual('foo');
|
|
77
112
|
});
|
|
78
113
|
|
|
79
|
-
test('passing additional CSS classes', () => {
|
|
114
|
+
test('passing additional CSS classes to breadcrumb item', () => {
|
|
80
115
|
render(
|
|
81
|
-
<Breadcrumbs
|
|
82
|
-
items={ITEMS}
|
|
83
|
-
className="foo"
|
|
84
|
-
/>
|
|
116
|
+
<Breadcrumbs.Item className="foo"/>
|
|
85
117
|
);
|
|
86
118
|
|
|
87
|
-
const nav = screen.getByRole('
|
|
119
|
+
const nav = screen.getByRole('listitem');
|
|
88
120
|
expect(nav).toHaveClass('foo');
|
|
89
121
|
});
|
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
1
|
+
const BreadcrumbItem = ({
|
|
2
|
+
children,
|
|
3
|
+
isHidden,
|
|
3
4
|
href,
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
linkComponent,
|
|
6
|
+
...props
|
|
7
|
+
}: SGDS.Component.Breadcrumbs.Item) => {
|
|
8
|
+
const BREADCRUMB_LINK_CLASSNAME = 'ds_breadcrumbs__link';
|
|
9
|
+
|
|
10
|
+
function processChildren(children: React.ReactNode) {
|
|
11
|
+
if (linkComponent) {
|
|
12
|
+
return linkComponent({ className: BREADCRUMB_LINK_CLASSNAME, href, children });
|
|
13
|
+
} else if (href) {
|
|
14
|
+
return <a href={href} className={BREADCRUMB_LINK_CLASSNAME}>{children}</a>;
|
|
15
|
+
} else {
|
|
16
|
+
return children;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
6
20
|
return (
|
|
7
|
-
<li
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
21
|
+
<li className={[
|
|
22
|
+
'ds_breadcrumbs__item',
|
|
23
|
+
isHidden && 'visually-hidden'
|
|
24
|
+
].join(' ')}
|
|
25
|
+
{...props}
|
|
12
26
|
>
|
|
13
|
-
|
|
14
|
-
{href ? (<a className="ds_breadcrumbs__link" href={href}>
|
|
15
|
-
{title}
|
|
16
|
-
</a>) : (title)}
|
|
27
|
+
{processChildren(children)}
|
|
17
28
|
</li>
|
|
18
29
|
);
|
|
19
30
|
};
|
|
20
31
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
* @param {Array} items
|
|
24
|
-
* @param {Object} props - Properties for the element
|
|
25
|
-
* @returns {JSX.Element} - The element
|
|
26
|
-
*/
|
|
27
|
-
const Breadcrumbs: React.FC<SGDS.Component.Breadcrumbs> = ({
|
|
28
|
-
hideLastItem,
|
|
29
|
-
items,
|
|
32
|
+
const Breadcrumbs = ({
|
|
33
|
+
children,
|
|
30
34
|
...props
|
|
31
|
-
}) => {
|
|
35
|
+
}: SGDS.Component.Breadcrumbs & { Item: SGDS.Component.Breadcrumbs.Item }) => {
|
|
32
36
|
return (
|
|
33
37
|
<nav
|
|
34
38
|
aria-label="Breadcrumb"
|
|
35
39
|
{...props}
|
|
36
40
|
>
|
|
37
41
|
<ol className="ds_breadcrumbs">
|
|
38
|
-
{
|
|
39
|
-
<Breadcrumb
|
|
40
|
-
title={item.title}
|
|
41
|
-
href={item.href}
|
|
42
|
-
hidden={(hideLastItem) && index + 1 === items.length}
|
|
43
|
-
key={'breadcrumb' + index}
|
|
44
|
-
/>
|
|
45
|
-
))}
|
|
42
|
+
{children}
|
|
46
43
|
</ol>
|
|
47
44
|
</nav>
|
|
48
45
|
);
|
|
49
46
|
};
|
|
50
47
|
|
|
51
48
|
Breadcrumbs.displayName = 'Breadcrumbs';
|
|
49
|
+
BreadcrumbItem.displayName = 'Breadcrumbs.Item';
|
|
50
|
+
|
|
51
|
+
Breadcrumbs.Item = BreadcrumbItem;
|
|
52
52
|
|
|
53
53
|
export default Breadcrumbs;
|
|
@@ -2,7 +2,7 @@ import Icon from '../../common/Icon';
|
|
|
2
2
|
import ScreenReaderText from '../../common/ScreenReaderText';
|
|
3
3
|
import WrapperTag from '../../common/WrapperTag';
|
|
4
4
|
|
|
5
|
-
const Button
|
|
5
|
+
const Button = ({
|
|
6
6
|
buttonStyle,
|
|
7
7
|
children,
|
|
8
8
|
className,
|
|
@@ -15,7 +15,7 @@ const Button: React.FC<SGDS.Component.Button> = ({
|
|
|
15
15
|
type = 'button',
|
|
16
16
|
width,
|
|
17
17
|
...props
|
|
18
|
-
}) => {
|
|
18
|
+
}: SGDS.Component.Button) => {
|
|
19
19
|
// determine which HTML tag to use
|
|
20
20
|
let tagName = 'button';
|
|
21
21
|
if (href) {
|