@scottish-government/designsystem-react 0.7.0 → 0.8.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/@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/Accordion.d.ts +0 -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 +12 -7
- package/dist/components/Breadcrumbs/Breadcrumbs.jsx +20 -15
- package/dist/components/Checkbox/Checkbox.jsx +4 -29
- package/dist/components/{aspect-box/aspect-box.jsx → Checkbox/CheckboxGroup.jsx} +14 -30
- 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 +7 -17
- package/dist/components/RadioButton/RadioGroup.jsx +21 -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/hooks/useTracking.js +21 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/context.js +5 -0
- package/package.json +2 -2
- 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 +17 -4
- package/src/components/Accordion/Accordion.tsx +19 -14
- package/src/components/AspectBox/AspectBox.tsx +2 -2
- package/src/components/BackToTop/BackToTop.tsx +2 -2
- package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +79 -48
- 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 +8 -55
- package/src/components/Checkbox/CheckboxGroup.test.tsx +37 -0
- package/src/components/Checkbox/CheckboxGroup.tsx +41 -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 +10 -41
- package/src/components/RadioButton/RadioGroup.test.tsx +65 -0
- package/src/components/RadioButton/RadioGroup.tsx +31 -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/src/hooks/useTracking.test.tsx +64 -0
- package/src/hooks/useTracking.ts +19 -0
- package/src/utils/context.ts +3 -0
- package/tsconfig.json +1 -1
- 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/icon.jsx +0 -57
- 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
|
@@ -1,31 +1,51 @@
|
|
|
1
1
|
import Icon from "../../common/Icon";
|
|
2
2
|
|
|
3
|
-
export const Page
|
|
3
|
+
export const Page = ({
|
|
4
4
|
ariaLabel,
|
|
5
|
+
children,
|
|
6
|
+
className,
|
|
5
7
|
current = false,
|
|
6
8
|
href,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}) => {
|
|
9
|
+
linkComponent,
|
|
10
|
+
onClick
|
|
11
|
+
}: SGDS.Component.Pagination.Page) => {
|
|
10
12
|
function handleClick(event: React.MouseEvent) {
|
|
11
13
|
if (typeof onClick === 'function') {
|
|
12
14
|
onClick(event);
|
|
13
15
|
}
|
|
14
16
|
}
|
|
15
17
|
|
|
18
|
+
function processChildren(children: React.ReactNode) {
|
|
19
|
+
const classNames = [
|
|
20
|
+
'ds_pagination__link',
|
|
21
|
+
className,
|
|
22
|
+
current ? 'ds_current' : undefined
|
|
23
|
+
].join(' ');
|
|
24
|
+
|
|
25
|
+
const linkProps: SGDS.LinkComponentProps = {
|
|
26
|
+
'aria-label': ariaLabel,
|
|
27
|
+
href: href,
|
|
28
|
+
onClick: handleClick
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
if (current) {
|
|
32
|
+
linkProps['aria-current'] = 'page';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (linkComponent) {
|
|
36
|
+
return linkComponent({ className: classNames, children: children, ...linkProps });
|
|
37
|
+
} else if (href) {
|
|
38
|
+
return (
|
|
39
|
+
<a href={href} className={classNames} {...linkProps}>
|
|
40
|
+
{children}
|
|
41
|
+
</a>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
16
46
|
return (
|
|
17
47
|
<li className="ds_pagination__item">
|
|
18
|
-
|
|
19
|
-
className={[
|
|
20
|
-
'ds_pagination__link',
|
|
21
|
-
current ? 'ds_current' : undefined
|
|
22
|
-
].join(' ')}
|
|
23
|
-
href={href}
|
|
24
|
-
aria-current={current ? "page" : undefined}
|
|
25
|
-
onClick={handleClick}
|
|
26
|
-
>
|
|
27
|
-
<span className="ds_pagination__link-label">{text}</span>
|
|
28
|
-
</a>
|
|
48
|
+
{processChildren(children)}
|
|
29
49
|
</li>
|
|
30
50
|
);
|
|
31
51
|
};
|
|
@@ -38,7 +58,7 @@ export const Ellipsis = () => {
|
|
|
38
58
|
);
|
|
39
59
|
};
|
|
40
60
|
|
|
41
|
-
const Pagination
|
|
61
|
+
const Pagination = ({
|
|
42
62
|
ariaLabel = 'Pages',
|
|
43
63
|
className,
|
|
44
64
|
onClick,
|
|
@@ -46,8 +66,9 @@ const Pagination: React.FC<SGDS.Component.Pagination> = ({
|
|
|
46
66
|
page = 1,
|
|
47
67
|
pattern = '/search?page=$1',
|
|
48
68
|
totalPages,
|
|
69
|
+
linkComponent,
|
|
49
70
|
...props
|
|
50
|
-
}) => {
|
|
71
|
+
}: SGDS.Component.Pagination) => {
|
|
51
72
|
padding = Number(padding);
|
|
52
73
|
page = Number(page);
|
|
53
74
|
|
|
@@ -93,12 +114,16 @@ const Pagination: React.FC<SGDS.Component.Pagination> = ({
|
|
|
93
114
|
>
|
|
94
115
|
<ul className="ds_pagination__list">
|
|
95
116
|
{page > 1 && (
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
117
|
+
<Page
|
|
118
|
+
ariaLabel="Previous page"
|
|
119
|
+
className="ds_pagination__link--text ds_pagination__link--icon"
|
|
120
|
+
data-search="pagination-previous"
|
|
121
|
+
href={pattern.replace('$1', String(page - 1))}
|
|
122
|
+
onClick={onClick}
|
|
123
|
+
>
|
|
124
|
+
<Icon icon="ChevronLeft" />
|
|
125
|
+
<span className="ds_pagination__link-label">Previous</span>
|
|
126
|
+
</Page>
|
|
102
127
|
)}
|
|
103
128
|
|
|
104
129
|
{includeFirst && (
|
|
@@ -107,8 +132,10 @@ const Pagination: React.FC<SGDS.Component.Pagination> = ({
|
|
|
107
132
|
ariaLabel="Page 1"
|
|
108
133
|
href={pattern.replace('$1', String(1))}
|
|
109
134
|
onClick={onClick}
|
|
110
|
-
|
|
111
|
-
|
|
135
|
+
linkComponent={linkComponent}
|
|
136
|
+
>
|
|
137
|
+
<span className="ds_pagination__link-label">1</span>
|
|
138
|
+
</Page>
|
|
112
139
|
<Ellipsis/>
|
|
113
140
|
</>
|
|
114
141
|
)}
|
|
@@ -116,13 +143,15 @@ const Pagination: React.FC<SGDS.Component.Pagination> = ({
|
|
|
116
143
|
{pages && pages.map((item, index: number) => (
|
|
117
144
|
<Page
|
|
118
145
|
ariaLabel={`Page ${item}`}
|
|
119
|
-
current={item === page}
|
|
120
146
|
href={pattern.replace('$1', String(item))}
|
|
147
|
+
current={item === page}
|
|
121
148
|
key={`pagination${index}`}
|
|
149
|
+
linkComponent={linkComponent}
|
|
122
150
|
onClick={onClick}
|
|
123
151
|
pattern={pattern}
|
|
124
|
-
|
|
125
|
-
|
|
152
|
+
>
|
|
153
|
+
<span className="ds_pagination__link-label">{item.toString()}</span>
|
|
154
|
+
</Page>
|
|
126
155
|
))}
|
|
127
156
|
|
|
128
157
|
{includeLast && (
|
|
@@ -131,20 +160,25 @@ const Pagination: React.FC<SGDS.Component.Pagination> = ({
|
|
|
131
160
|
<Page
|
|
132
161
|
ariaLabel={`Page ${totalPages}`}
|
|
133
162
|
href={pattern.replace('$1', String(totalPages))}
|
|
163
|
+
linkComponent={linkComponent}
|
|
134
164
|
onClick={onClick}
|
|
135
165
|
pattern={pattern}
|
|
136
|
-
|
|
137
|
-
|
|
166
|
+
>
|
|
167
|
+
<span className="ds_pagination__link-label">{totalPages.toString()}</span>
|
|
168
|
+
</Page>
|
|
138
169
|
</>
|
|
139
170
|
)}
|
|
140
171
|
|
|
141
172
|
{page < totalPages && (
|
|
142
|
-
<
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
173
|
+
<Page
|
|
174
|
+
ariaLabel="Next page"
|
|
175
|
+
href={pattern.replace('$1', String(page + 1))}
|
|
176
|
+
className="ds_pagination__link ds_pagination__link--text ds_pagination__link--icon"
|
|
177
|
+
onClick={onClick}
|
|
178
|
+
>
|
|
179
|
+
<span className="ds_pagination__link-label">Next</span>
|
|
180
|
+
<Icon icon="ChevronRight" />
|
|
181
|
+
</Page>
|
|
148
182
|
)}
|
|
149
183
|
|
|
150
184
|
</ul>
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import Tag from "../Tag/Tag";
|
|
2
2
|
|
|
3
|
-
const PhaseBanner
|
|
3
|
+
const PhaseBanner = ({
|
|
4
4
|
children,
|
|
5
5
|
className,
|
|
6
|
-
content,
|
|
7
6
|
phaseName,
|
|
8
7
|
...props
|
|
9
|
-
}) => {
|
|
8
|
+
}: SGDS.Component.PhaseBanner) => {
|
|
10
9
|
return (
|
|
11
10
|
<div
|
|
12
11
|
className={[
|
|
@@ -17,9 +16,9 @@ const PhaseBanner: React.FC<SGDS.Component.PhaseBanner> = ({
|
|
|
17
16
|
>
|
|
18
17
|
<div className="ds_wrapper">
|
|
19
18
|
<p className="ds_phase-banner__content">
|
|
20
|
-
{phaseName && <Tag
|
|
19
|
+
{phaseName && <Tag className="ds_phase-banner__tag">{phaseName}</Tag>}
|
|
21
20
|
<span className="ds_phase-banner__text">
|
|
22
|
-
{
|
|
21
|
+
{children || "This is a new service"}
|
|
23
22
|
</span>
|
|
24
23
|
</p>
|
|
25
24
|
</div>
|
|
@@ -2,29 +2,29 @@ import ErrorMessage from '../ErrorMessage/ErrorMessage';
|
|
|
2
2
|
import HintText from '../../common/HintText';
|
|
3
3
|
import WrapperTag from '../../common/WrapperTag';
|
|
4
4
|
|
|
5
|
-
const Question
|
|
5
|
+
const Question = function ({
|
|
6
6
|
children,
|
|
7
7
|
className,
|
|
8
|
-
error,
|
|
9
8
|
errorMessage,
|
|
9
|
+
hasError,
|
|
10
10
|
hintText,
|
|
11
11
|
legend,
|
|
12
12
|
tagName = 'div',
|
|
13
13
|
...props
|
|
14
|
-
}) {
|
|
14
|
+
}: SGDS.Component.Question) {
|
|
15
15
|
return (
|
|
16
16
|
<WrapperTag
|
|
17
17
|
tagName={tagName}
|
|
18
18
|
className={[
|
|
19
19
|
'ds_question',
|
|
20
|
-
|
|
20
|
+
hasError && 'ds_question--error',
|
|
21
21
|
className
|
|
22
22
|
].join(' ')}
|
|
23
23
|
{...props}
|
|
24
24
|
>
|
|
25
25
|
{legend && <legend>{legend}</legend>}
|
|
26
26
|
{hintText && <HintText text={hintText} />}
|
|
27
|
-
{
|
|
27
|
+
{hasError && errorMessage && <ErrorMessage text={errorMessage} />}
|
|
28
28
|
{children}
|
|
29
29
|
</WrapperTag>
|
|
30
30
|
);
|
|
@@ -1,103 +1,10 @@
|
|
|
1
1
|
import { test, expect, vi } from 'vitest';
|
|
2
2
|
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
test('radio 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
|
-
id: 'none',
|
|
22
|
-
label: 'I do not receive any of these benefits',
|
|
23
|
-
}
|
|
24
|
-
];
|
|
25
|
-
const GROUP_NAME = "foo"
|
|
26
|
-
|
|
27
|
-
render(
|
|
28
|
-
<RadioGroup name={GROUP_NAME} items={ITEMS} />
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
const radios = screen.getAllByRole('radio');
|
|
32
|
-
const groupContainer = radios[0].parentElement?.parentElement;
|
|
33
|
-
expect(radios.length).toEqual(ITEMS.length);
|
|
34
|
-
expect(groupContainer).toHaveClass('ds_radios', 'ds_field-group');
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test('inline radio group', () => {
|
|
38
|
-
const ITEMS = [
|
|
39
|
-
{
|
|
40
|
-
id: 'radio-yes',
|
|
41
|
-
label: 'Yes'
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
id: 'radio-no',
|
|
45
|
-
label: 'No'
|
|
46
|
-
}
|
|
47
|
-
];
|
|
48
|
-
const GROUP_NAME = "yesno"
|
|
49
|
-
|
|
50
|
-
render(
|
|
51
|
-
<RadioGroup inline name={GROUP_NAME} items={ITEMS} />
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const radio = screen.getAllByRole('radio')[0];
|
|
56
|
-
const groupContainer = radio.parentElement?.parentElement;
|
|
57
|
-
expect(groupContainer).toHaveClass('ds_field-group--inline');
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test('radio group passes all expected item params', () => {
|
|
61
|
-
const ONBLUR_FUNCTION = vi.fn();
|
|
62
|
-
const ONCHANGE_FUNCTION = vi.fn();
|
|
63
|
-
const GROUP_NAME = "foo"
|
|
64
|
-
|
|
65
|
-
render(
|
|
66
|
-
<RadioGroup name={GROUP_NAME} small items={[
|
|
67
|
-
{
|
|
68
|
-
checked: true,
|
|
69
|
-
exclusive: true,
|
|
70
|
-
hintText: 'hint text',
|
|
71
|
-
id: 'myid',
|
|
72
|
-
label: 'label text',
|
|
73
|
-
onBlur: {ONBLUR_FUNCTION},
|
|
74
|
-
onChange: {ONCHANGE_FUNCTION},
|
|
75
|
-
small: true
|
|
76
|
-
}
|
|
77
|
-
]}/>
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
const radio = screen.getByRole('radio');
|
|
81
|
-
const radioContainer = radio.parentElement;
|
|
82
|
-
const hintText = screen.getByText('hint text');
|
|
83
|
-
|
|
84
|
-
expect(radio).toHaveAttribute('checked');
|
|
85
|
-
expect(radio).toHaveAttribute('name', GROUP_NAME);
|
|
86
|
-
expect(radio.id).toEqual('myid');
|
|
87
|
-
expect(radioContainer).toHaveClass('ds_radio--small');
|
|
88
|
-
expect(hintText).toBeInTheDocument();
|
|
89
|
-
expect(radio).toHaveAttribute('aria-describedby', hintText.id);
|
|
90
|
-
|
|
91
|
-
// fireEvent.blur(radio);
|
|
92
|
-
// expect(ONBLUR_FUNCTION).toHaveBeenCalled();
|
|
93
|
-
|
|
94
|
-
// fireEvent.click(radio);
|
|
95
|
-
// expect(ONCHANGE_FUNCTION).toHaveBeenCalled();
|
|
96
|
-
});
|
|
3
|
+
import RadioButton from './RadioButton';
|
|
97
4
|
|
|
98
5
|
test('individual radio renders correctly', () => {
|
|
99
6
|
render(
|
|
100
|
-
<
|
|
7
|
+
<RadioButton name="benefitType" label="Pension Credit" id="pensioncredit" />
|
|
101
8
|
);
|
|
102
9
|
|
|
103
10
|
const radio = screen.getByRole('radio');
|
|
@@ -117,7 +24,7 @@ test('individual radio renders correctly', () => {
|
|
|
117
24
|
|
|
118
25
|
test('checked radio', () => {
|
|
119
26
|
render(
|
|
120
|
-
<
|
|
27
|
+
<RadioButton name="benefitType" checked label="Pension Credit" id="pensioncredit" />
|
|
121
28
|
);
|
|
122
29
|
|
|
123
30
|
const radio = screen.getByRole('radio');
|
|
@@ -129,7 +36,7 @@ test('radio with blur fn', () => {
|
|
|
129
36
|
const ONBLUR_FUNCTION = vi.fn();
|
|
130
37
|
|
|
131
38
|
render(
|
|
132
|
-
<
|
|
39
|
+
<RadioButton onBlur={ONBLUR_FUNCTION} name="benefitType" label="Pension Credit" id="pensioncredit" />
|
|
133
40
|
);
|
|
134
41
|
|
|
135
42
|
const radio = screen.getByRole('radio');
|
|
@@ -143,7 +50,7 @@ test('radio with change fn', () => {
|
|
|
143
50
|
const ONCHANGE_FUNCTION = vi.fn();
|
|
144
51
|
|
|
145
52
|
render(
|
|
146
|
-
<
|
|
53
|
+
<RadioButton onChange={ONCHANGE_FUNCTION} name="benefitType" label="Pension Credit" id="pensioncredit" />
|
|
147
54
|
);
|
|
148
55
|
|
|
149
56
|
const radio = screen.getByRole('radio');
|
|
@@ -155,7 +62,7 @@ test('radio with change fn', () => {
|
|
|
155
62
|
|
|
156
63
|
test('radio with hint text', () => {
|
|
157
64
|
render(
|
|
158
|
-
<
|
|
65
|
+
<RadioButton hintText="hint text" name="benefitType" label="Pension Credit" id="pensioncredit" />
|
|
159
66
|
);
|
|
160
67
|
|
|
161
68
|
const hintText = screen.getByText('hint text');
|
|
@@ -167,7 +74,7 @@ test('radio with hint text', () => {
|
|
|
167
74
|
|
|
168
75
|
test('small radio', () => {
|
|
169
76
|
render(
|
|
170
|
-
<
|
|
77
|
+
<RadioButton small name="benefitType" label="Pension Credit" id="pensioncredit" />
|
|
171
78
|
);
|
|
172
79
|
|
|
173
80
|
const radio = screen.getByRole('radio');
|
|
@@ -175,29 +82,3 @@ test('small radio', () => {
|
|
|
175
82
|
|
|
176
83
|
expect(radioContainer).toHaveClass('ds_radio--small');
|
|
177
84
|
});
|
|
178
|
-
|
|
179
|
-
test('passing additional props', () => {
|
|
180
|
-
render(
|
|
181
|
-
<RadioGroup data-test="foo" items={[{
|
|
182
|
-
id: 'universal-credit',
|
|
183
|
-
label: 'Universal Credit'
|
|
184
|
-
}]} />
|
|
185
|
-
);
|
|
186
|
-
|
|
187
|
-
const radios = screen.getAllByRole('radio');
|
|
188
|
-
const groupContainer = radios[0]?.parentElement?.parentElement;
|
|
189
|
-
expect(groupContainer?.dataset.test).toEqual('foo');
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
test('passing additional CSS classes', () => {
|
|
193
|
-
render(
|
|
194
|
-
<RadioGroup className="foo" items={[{
|
|
195
|
-
id: 'universal-credit',
|
|
196
|
-
label: 'Universal Credit'
|
|
197
|
-
}]} />
|
|
198
|
-
);
|
|
199
|
-
|
|
200
|
-
const radios = screen.getAllByRole('radio');
|
|
201
|
-
const groupContainer = radios[0]?.parentElement?.parentElement;
|
|
202
|
-
expect(groupContainer).toHaveClass('foo', 'ds_radios');
|
|
203
|
-
});
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
|
|
1
3
|
import HintText from '../../common/HintText';
|
|
4
|
+
import { CheckboxRadioContext } from '../../utils/context';
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
const RadioButton = ({
|
|
4
7
|
checked,
|
|
5
8
|
hintText,
|
|
6
9
|
id,
|
|
@@ -9,7 +12,7 @@ export const Radio: React.FC<SGDS.Component.RadioButton> = ({
|
|
|
9
12
|
onBlur,
|
|
10
13
|
onChange,
|
|
11
14
|
small
|
|
12
|
-
}) => {
|
|
15
|
+
}: SGDS.Component.RadioButton) => {
|
|
13
16
|
const hintTextId = `hint-text-${id}`;
|
|
14
17
|
|
|
15
18
|
function handleBlur(event: React.FocusEvent) {
|
|
@@ -24,6 +27,9 @@ export const Radio: React.FC<SGDS.Component.RadioButton> = ({
|
|
|
24
27
|
}
|
|
25
28
|
}
|
|
26
29
|
|
|
30
|
+
small = small || useContext(CheckboxRadioContext).small;
|
|
31
|
+
name = name || useContext(CheckboxRadioContext).name;
|
|
32
|
+
|
|
27
33
|
return (
|
|
28
34
|
<div
|
|
29
35
|
className={[
|
|
@@ -48,43 +54,6 @@ export const Radio: React.FC<SGDS.Component.RadioButton> = ({
|
|
|
48
54
|
);
|
|
49
55
|
};
|
|
50
56
|
|
|
51
|
-
|
|
52
|
-
className,
|
|
53
|
-
inline,
|
|
54
|
-
items,
|
|
55
|
-
name,
|
|
56
|
-
small,
|
|
57
|
-
...props
|
|
58
|
-
}) => {
|
|
59
|
-
return (
|
|
60
|
-
<div
|
|
61
|
-
className={[
|
|
62
|
-
'ds_radios',
|
|
63
|
-
'ds_field-group',
|
|
64
|
-
inline && 'ds_field-group--inline',
|
|
65
|
-
className
|
|
66
|
-
].join(' ')}
|
|
67
|
-
{...props}
|
|
68
|
-
>
|
|
69
|
-
|
|
70
|
-
{items && items.map((item, index: number) => (
|
|
71
|
-
<Radio
|
|
72
|
-
checked={item.checked}
|
|
73
|
-
hintText={item.hintText}
|
|
74
|
-
id={item.id}
|
|
75
|
-
key={'radio' + index}
|
|
76
|
-
label={item.label}
|
|
77
|
-
name={name}
|
|
78
|
-
onBlur={item.onBlur}
|
|
79
|
-
onChange={item.onChange}
|
|
80
|
-
small={small || item.small}
|
|
81
|
-
/>
|
|
82
|
-
))}
|
|
83
|
-
</div>
|
|
84
|
-
)
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
Radio.displayName = 'Radio';
|
|
88
|
-
RadioGroup.displayName = 'RadioGroup';
|
|
57
|
+
RadioButton.displayName = 'RadioButton';
|
|
89
58
|
|
|
90
|
-
export default
|
|
59
|
+
export default RadioButton;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { test, expect } from 'vitest';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import RadioButton from './RadioButton';
|
|
4
|
+
import RadioGroup from './RadioGroup';
|
|
5
|
+
|
|
6
|
+
test('radio group renders correctly', () => {
|
|
7
|
+
render(
|
|
8
|
+
<RadioGroup name="foo" data-testid="radiogroup">
|
|
9
|
+
<RadioButton id="banana" label="Banana" />
|
|
10
|
+
</RadioGroup>
|
|
11
|
+
);
|
|
12
|
+
const radioGroup = screen.getByTestId('radiogroup');
|
|
13
|
+
expect(radioGroup).toHaveClass('ds_radios', 'ds_field-group');
|
|
14
|
+
expect(radioGroup).not.toHaveClass('ds_field-group--inline');
|
|
15
|
+
|
|
16
|
+
const radio = screen.getByRole('radio');
|
|
17
|
+
const radioContainer = radio.parentElement;
|
|
18
|
+
expect(radioContainer).not.toHaveClass('ds_radio--small');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('radio group passes all expected item params', () => {
|
|
22
|
+
const RADIO_NAME = 'radioname';
|
|
23
|
+
|
|
24
|
+
render(
|
|
25
|
+
<RadioGroup name={RADIO_NAME} small>
|
|
26
|
+
<RadioButton id="banana" />
|
|
27
|
+
<p>foo</p>
|
|
28
|
+
</RadioGroup>
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const radio = screen.getByRole('radio');
|
|
32
|
+
const radioContainer = radio.parentElement;
|
|
33
|
+
expect(radio).toHaveAttribute('name', RADIO_NAME);
|
|
34
|
+
expect(radioContainer).toHaveClass('ds_radio--small');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('inline radio group', () => {
|
|
38
|
+
render(
|
|
39
|
+
<RadioGroup inline>
|
|
40
|
+
<RadioButton id="banana" />
|
|
41
|
+
</RadioGroup>
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const radio = screen.getAllByRole('radio')[0];
|
|
45
|
+
const groupContainer = radio.parentElement?.parentElement;
|
|
46
|
+
expect(groupContainer).toHaveClass('ds_field-group--inline');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('passing additional props', () => {
|
|
50
|
+
render(
|
|
51
|
+
<RadioGroup data-test="foo" data-testid="radiogroup"/>
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const radioGroup = screen.getByTestId('radiogroup');
|
|
55
|
+
expect(radioGroup?.dataset.test).toEqual('foo');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('passing additional CSS classes', () => {
|
|
59
|
+
render(
|
|
60
|
+
<RadioGroup className="foo" data-testid="radiogroup"/>
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const radioGroup = screen.getByTestId('radiogroup');
|
|
64
|
+
expect(radioGroup).toHaveClass('foo');
|
|
65
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { CheckboxRadioContext } from '../../utils/context';
|
|
3
|
+
|
|
4
|
+
const RadioGroup = ({
|
|
5
|
+
children,
|
|
6
|
+
className,
|
|
7
|
+
inline,
|
|
8
|
+
name,
|
|
9
|
+
small = false,
|
|
10
|
+
...props
|
|
11
|
+
}: SGDS.Component.RadioButton.Group) => {
|
|
12
|
+
return (
|
|
13
|
+
<div
|
|
14
|
+
className={[
|
|
15
|
+
'ds_radios',
|
|
16
|
+
'ds_field-group',
|
|
17
|
+
inline && 'ds_field-group--inline',
|
|
18
|
+
className
|
|
19
|
+
].join(' ')}
|
|
20
|
+
{...props}
|
|
21
|
+
>
|
|
22
|
+
<CheckboxRadioContext value={{ small, name }}>
|
|
23
|
+
{children}
|
|
24
|
+
</CheckboxRadioContext>
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
RadioGroup.displayName = 'RadioGroup';
|
|
30
|
+
|
|
31
|
+
export default RadioGroup;
|