@nypl/design-system-react-components 0.25.0 → 0.25.1
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/CHANGELOG.md +30 -0
- package/dist/components/Accordion/Accordion.d.ts +14 -14
- package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +11 -14
- package/dist/components/Breadcrumbs/BreadcrumbsTypes.d.ts +6 -0
- package/dist/components/Button/ButtonTypes.d.ts +2 -1
- package/dist/components/Card/Card.d.ts +1 -1
- package/dist/components/Card/CardTypes.d.ts +2 -2
- package/dist/components/CheckboxGroup/CheckboxGroup.d.ts +43 -0
- package/dist/components/CheckboxGroup/CheckboxGroupLayoutTypes.d.ts +4 -0
- package/dist/components/DatePicker/DatePicker.d.ts +3 -3
- package/dist/components/Form/Form.d.ts +13 -8
- package/dist/components/Form/FormTypes.d.ts +2 -8
- package/dist/components/Grid/GridTypes.d.ts +9 -0
- package/dist/components/Grid/SimpleGrid.d.ts +14 -0
- package/dist/components/Heading/Heading.d.ts +4 -4
- package/dist/components/Hero/Hero.d.ts +19 -14
- package/dist/components/Hero/HeroTypes.d.ts +10 -5
- package/dist/components/Icons/Icon.d.ts +13 -16
- package/dist/components/Icons/IconTypes.d.ts +78 -64
- package/dist/components/Label/Label.d.ts +5 -17
- package/dist/components/Link/Link.d.ts +8 -12
- package/dist/components/SearchBar/SearchBar.d.ts +45 -27
- package/dist/components/Select/Select.d.ts +32 -35
- package/dist/components/Select/SelectTypes.d.ts +4 -0
- package/dist/components/SkeletonLoader/SkeletonLoader.d.ts +1 -1
- package/dist/components/SkeletonLoader/SkeletonLoaderTypes.d.ts +2 -2
- package/dist/components/StatusBadge/StatusBadge.d.ts +8 -6
- package/dist/components/StatusBadge/StatusBadgeTypes.d.ts +5 -0
- package/dist/components/Template/Template.d.ts +91 -0
- package/dist/components/Text/Text.d.ts +16 -0
- package/dist/components/Text/TextTypes.d.ts +6 -0
- package/dist/components/TextInput/TextInput.d.ts +32 -31
- package/dist/components/TextInput/TextInputTypes.d.ts +5 -0
- package/dist/design-system-react-components.cjs.development.js +2597 -1170
- package/dist/design-system-react-components.cjs.development.js.map +1 -1
- package/dist/design-system-react-components.cjs.production.min.js +1 -1
- package/dist/design-system-react-components.cjs.production.min.js.map +1 -1
- package/dist/design-system-react-components.esm.js +2580 -1173
- package/dist/design-system-react-components.esm.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/styles.css +1 -1
- package/dist/theme/components/accordion.d.ts +25 -0
- package/dist/theme/components/breadcrumb.d.ts +90 -0
- package/dist/theme/components/button.d.ts +17 -7
- package/dist/theme/components/checkbox.d.ts +7 -7
- package/dist/theme/components/customCheckboxGroup.d.ts +18 -0
- package/dist/theme/components/customRadioGroup.d.ts +4 -3
- package/dist/theme/components/global.d.ts +55 -0
- package/dist/theme/components/globalMixins.d.ts +15 -0
- package/dist/theme/components/heading.d.ts +50 -20
- package/dist/theme/components/hero.d.ts +492 -0
- package/dist/theme/components/icon.d.ts +13 -0
- package/dist/theme/components/label.d.ts +16 -0
- package/dist/theme/components/link.d.ts +45 -0
- package/dist/theme/components/radio.d.ts +8 -7
- package/dist/theme/components/searchBar.d.ts +20 -0
- package/dist/theme/components/select.d.ts +58 -0
- package/dist/theme/components/statusBadge.d.ts +25 -0
- package/dist/theme/components/tabs.d.ts +9 -9
- package/dist/theme/components/template.d.ts +105 -0
- package/dist/theme/components/text.d.ts +20 -0
- package/dist/theme/components/textInput.d.ts +105 -0
- package/dist/theme/foundations/global.d.ts +3 -0
- package/dist/theme/foundations/shadows.d.ts +4 -0
- package/dist/utils/utils.d.ts +6 -0
- package/package.json +3 -2
- package/src/components/Accordion/Accordion.stories.mdx +227 -33
- package/src/components/Accordion/Accordion.test.tsx +135 -19
- package/src/components/Accordion/Accordion.tsx +81 -56
- package/src/components/Autosuggest/Autosuggest.stories.mdx +1 -1
- package/src/components/Autosuggest/Autosuggest.stories.tsx +1 -1
- package/src/components/Autosuggest/_Autosuggest.scss +2 -2
- package/src/components/Breadcrumbs/Breadcrumbs.stories.mdx +46 -52
- package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +31 -25
- package/src/components/Breadcrumbs/Breadcrumbs.tsx +71 -73
- package/src/components/Breadcrumbs/BreadcrumbsTypes.tsx +6 -0
- package/src/components/Breadcrumbs/__snapshots__/Breadcrumbs.test.tsx.snap +100 -0
- package/src/components/Button/Button.stories.mdx +31 -27
- package/src/components/Button/Button.test.tsx +17 -5
- package/src/components/Button/ButtonTypes.tsx +1 -0
- package/src/components/Button/_Button.scss +3 -27
- package/src/components/Button/__snapshots__/Button.test.tsx.snap +11 -0
- package/src/components/Card/Card.stories.mdx +24 -20
- package/src/components/Card/Card.test.tsx +13 -19
- package/src/components/Card/Card.tsx +1 -1
- package/src/components/Card/CardTypes.tsx +2 -2
- package/src/components/Card/_Card.scss +1 -1
- package/src/components/CardEdition/CardEdition.stories.tsx +11 -6
- package/src/components/CardEdition/CardEdition.test.tsx +23 -31
- package/src/components/CardEdition/_CardEdition.scss +2 -2
- package/src/components/Chakra/Center.stories.mdx +31 -14
- package/src/components/Chakra/Grid.stories.mdx +79 -0
- package/src/components/Chakra/Stack.stories.mdx +4 -4
- package/src/components/Checkbox/Checkbox.tsx +9 -12
- package/src/components/Checkbox/__snapshots__/Checkbox.test.tsx.snap +2 -5
- package/src/components/CheckboxGroup/CheckboxGroup.stories.mdx +249 -0
- package/src/components/CheckboxGroup/CheckboxGroup.test.tsx +345 -0
- package/src/components/CheckboxGroup/CheckboxGroup.tsx +148 -0
- package/src/components/CheckboxGroup/CheckboxGroupLayoutTypes.tsx +4 -0
- package/src/components/CheckboxGroup/__snapshots__/CheckboxGroup.test.tsx.snap +1360 -0
- package/src/components/DatePicker/DatePicker.test.tsx +4 -4
- package/src/components/DatePicker/DatePicker.tsx +13 -13
- package/src/components/DatePicker/_DatePicker.scss +1 -0
- package/src/components/Form/Form.stories.mdx +46 -21
- package/src/components/Form/Form.test.tsx +58 -45
- package/src/components/Form/Form.tsx +49 -21
- package/src/components/Form/FormTypes.tsx +3 -8
- package/src/components/Form/__snapshots__/Form.test.tsx.snap +24 -14
- package/src/components/Grid/GridTypes.tsx +9 -0
- package/src/components/Grid/SimpleGrid.stories.mdx +275 -0
- package/src/components/Grid/SimpleGrid.test.tsx +66 -0
- package/src/components/Grid/SimpleGrid.tsx +37 -0
- package/src/components/Grid/__snapshots__/SimpleGrid.test.tsx.snap +8 -0
- package/src/components/Heading/Heading.stories.mdx +1 -0
- package/src/components/Heading/Heading.tsx +12 -6
- package/src/components/HelperErrorText/_HelperErrorText.scss +1 -1
- package/src/components/Hero/Hero.stories.mdx +188 -121
- package/src/components/Hero/Hero.test.tsx +537 -107
- package/src/components/Hero/Hero.tsx +79 -92
- package/src/components/Hero/HeroTypes.tsx +17 -5
- package/src/components/Hero/__snapshots__/Hero.test.tsx.snap +307 -0
- package/src/components/HorizontalRule/_HorizontalRule.scss +1 -1
- package/src/components/Icons/Icon.stories.mdx +83 -74
- package/src/components/Icons/Icon.test.tsx +30 -22
- package/src/components/Icons/Icon.tsx +63 -61
- package/src/components/Icons/IconTypes.tsx +80 -64
- package/src/components/Input/_Input.scss +2 -2
- package/src/components/Label/Label.stories.mdx +28 -7
- package/src/components/Label/Label.test.tsx +43 -12
- package/src/components/Label/Label.tsx +21 -34
- package/src/components/Label/__snapshots__/Label.test.tsx.snap +41 -0
- package/src/components/Link/Link.stories.mdx +41 -41
- package/src/components/Link/Link.test.tsx +33 -44
- package/src/components/Link/Link.tsx +114 -100
- package/src/components/List/List.stories.mdx +0 -2
- package/src/components/List/List.stories.tsx +5 -5
- package/src/components/List/_List.scss +3 -3
- package/src/components/Modal/_Modal.scss +1 -1
- package/src/components/Notification/Notification.stories.mdx +12 -1
- package/src/components/Notification/Notification.test.tsx +3 -16
- package/src/components/Notification/Notification.tsx +9 -10
- package/src/components/Notification/_Notification.scss +4 -4
- package/src/components/Pagination/Pagination.test.tsx +16 -10
- package/src/components/RadioGroup/RadioGroup.stories.mdx +1 -1
- package/src/components/RadioGroup/RadioGroup.tsx +2 -10
- package/src/components/SearchBar/SearchBar.Test.tsx +151 -16
- package/src/components/SearchBar/SearchBar.stories.mdx +189 -219
- package/src/components/SearchBar/SearchBar.tsx +151 -46
- package/src/components/Select/Select.stories.mdx +188 -170
- package/src/components/Select/Select.test.tsx +125 -380
- package/src/components/Select/Select.tsx +118 -165
- package/src/components/Select/SelectTypes.tsx +4 -0
- package/src/components/SkeletonLoader/SkeletonLoader.stories.mdx +13 -25
- package/src/components/SkeletonLoader/SkeletonLoader.test.tsx +7 -7
- package/src/components/SkeletonLoader/SkeletonLoader.tsx +4 -2
- package/src/components/SkeletonLoader/SkeletonLoaderTypes.tsx +2 -2
- package/src/components/SkeletonLoader/_SkeletonLoader.scss +3 -3
- package/src/components/StatusBadge/StatusBadge.stories.mdx +91 -0
- package/src/components/StatusBadge/StatusBadge.test.tsx +35 -7
- package/src/components/StatusBadge/StatusBadge.tsx +24 -25
- package/src/components/StatusBadge/StatusBadgeTypes.tsx +5 -0
- package/src/components/StatusBadge/__snapshots__/StatusBadge.test.tsx.snap +28 -0
- package/src/components/StyleGuide/Bidirectionality.stories.mdx +16 -16
- package/src/components/StyleGuide/Buttons.stories.mdx +15 -15
- package/src/components/StyleGuide/Colors.stories.mdx +336 -0
- package/src/components/StyleGuide/Iconography.stories.mdx +88 -90
- package/src/components/StyleGuide/UIDocCard.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +7 -9
- package/src/components/Template/Template.stories.mdx +574 -0
- package/src/components/Template/Template.test.tsx +124 -0
- package/src/components/Template/Template.tsx +226 -0
- package/src/components/Text/Text.stories.mdx +70 -0
- package/src/components/Text/Text.test.tsx +63 -0
- package/src/components/Text/Text.tsx +55 -0
- package/src/components/Text/TextTypes.tsx +6 -0
- package/src/components/Text/__snapshots__/Text.test.tsx.snap +33 -0
- package/src/components/TextInput/TextInput.stories.mdx +89 -90
- package/src/components/TextInput/TextInput.test.tsx +65 -86
- package/src/components/TextInput/TextInput.tsx +101 -95
- package/src/components/TextInput/TextInputTypes.tsx +6 -0
- package/src/components/VideoPlayer/_VideoPlayer.scss +1 -1
- package/src/docs/Chakra.stories.mdx +4 -4
- package/src/docs/Intro.stories.mdx +15 -13
- package/src/index.ts +20 -0
- package/src/styles/01-colors/_colors-brand.scss +6 -0
- package/src/styles/01-colors/_colors-utility.scss +14 -12
- package/src/styles/base/_04-base.scss +2 -1
- package/src/styles/base/_place-holder.scss +1 -1
- package/src/styles.scss +10 -12
- package/src/theme/components/accordion.ts +30 -0
- package/src/theme/components/breadcrumb.ts +77 -0
- package/src/theme/components/button.ts +77 -63
- package/src/theme/components/checkbox.ts +15 -27
- package/src/theme/components/customCheckboxGroup.ts +12 -0
- package/src/theme/components/customRadioGroup.ts +4 -10
- package/src/theme/components/global.ts +71 -0
- package/src/theme/components/globalMixins.ts +16 -0
- package/src/theme/components/heading.ts +15 -8
- package/src/theme/components/hero.ts +239 -0
- package/src/theme/components/icon.ts +79 -0
- package/src/theme/components/label.ts +17 -0
- package/src/theme/components/link.ts +47 -0
- package/src/theme/components/radio.ts +20 -31
- package/src/theme/components/searchBar.ts +21 -0
- package/src/theme/components/select.ts +50 -0
- package/src/theme/components/statusBadge.ts +27 -0
- package/src/theme/components/tabs.ts +72 -69
- package/src/theme/components/template.ts +114 -0
- package/src/theme/components/text.ts +31 -0
- package/src/theme/components/textInput.ts +61 -0
- package/src/theme/foundations/colors.ts +29 -13
- package/src/theme/foundations/global.ts +3 -0
- package/src/theme/foundations/shadows.ts +5 -0
- package/src/theme/index.ts +37 -7
- package/src/utils/componentCategories.ts +8 -2
- package/src/utils/utils.ts +13 -0
- package/dist/components/Accordion/Accordion.stories.d.ts +0 -6
- package/dist/components/StatusBadge/StatusBadge.stories.d.ts +0 -8
- package/dist/components/StyleGuide/Colors.stories.d.ts +0 -25
- package/dist/components/Template/Template.stories.d.ts +0 -30
- package/src/components/Accordion/Accordion.stories.tsx +0 -66
- package/src/components/Accordion/_Accordion.scss +0 -81
- package/src/components/Breadcrumbs/_Breadcrumbs.scss +0 -97
- package/src/components/Form/_Form.scss +0 -67
- package/src/components/Hero/_Hero.scss +0 -256
- package/src/components/Icons/_Icons.scss +0 -116
- package/src/components/Label/_Label.scss +0 -22
- package/src/components/Link/_Link.scss +0 -73
- package/src/components/SearchBar/_SearchBar.scss +0 -16
- package/src/components/Select/_Select.scss +0 -82
- package/src/components/StatusBadge/StatusBadge.stories.tsx +0 -34
- package/src/components/StatusBadge/_StatusBadge.scss +0 -23
- package/src/components/StyleGuide/Colors.stories.tsx +0 -289
- package/src/components/Template/Template.stories.tsx +0 -86
- package/src/components/Template/_Template.scss +0 -63
- package/src/components/TextInput/_TextInput.scss +0 -59
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import { axe } from "jest-axe";
|
|
4
|
+
import renderer from "react-test-renderer";
|
|
5
|
+
|
|
6
|
+
import * as generateUUID from "../../helpers/generateUUID";
|
|
7
|
+
import CheckboxGroup from "./CheckboxGroup";
|
|
8
|
+
import Checkbox from "../Checkbox/Checkbox";
|
|
9
|
+
import { CheckboxGroupLayoutTypes } from "./CheckboxGroupLayoutTypes";
|
|
10
|
+
import userEvent from "@testing-library/user-event";
|
|
11
|
+
|
|
12
|
+
describe("Checkbox Accessibility", () => {
|
|
13
|
+
it("passes axe accessibility", async () => {
|
|
14
|
+
const { container } = render(
|
|
15
|
+
<CheckboxGroup labelText="CheckboxGroup example" name="a11y-test">
|
|
16
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
17
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
18
|
+
<Checkbox value="4" labelText="Checkbox 4" />
|
|
19
|
+
<Checkbox value="5" labelText="Checkbox 5" />
|
|
20
|
+
</CheckboxGroup>
|
|
21
|
+
);
|
|
22
|
+
expect(await axe(container)).toHaveNoViolations();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe("Checkbox", () => {
|
|
27
|
+
it("renders with Checkbox inputs and a label", () => {
|
|
28
|
+
render(
|
|
29
|
+
<CheckboxGroup labelText="Test Label" name="test1">
|
|
30
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
31
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
32
|
+
<Checkbox value="4" labelText="Checkbox 4" />
|
|
33
|
+
</CheckboxGroup>
|
|
34
|
+
);
|
|
35
|
+
expect(screen.getByText(/Test Label/i)).toBeInTheDocument();
|
|
36
|
+
expect(screen.getAllByRole("checkbox")).toHaveLength(3);
|
|
37
|
+
expect(screen.getByLabelText("Checkbox 2")).toBeInTheDocument();
|
|
38
|
+
expect(screen.getByLabelText("Checkbox 3")).toBeInTheDocument();
|
|
39
|
+
expect(screen.getByLabelText("Checkbox 4")).toBeInTheDocument();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("renders with appropriate 'aria-label' attribute and value when 'showLabel' prop is set to false", () => {
|
|
43
|
+
const { rerender } = render(
|
|
44
|
+
<CheckboxGroup labelText="Test Label" name="test2">
|
|
45
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
46
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
47
|
+
<Checkbox value="4" labelText="Checkbox 4" />
|
|
48
|
+
</CheckboxGroup>
|
|
49
|
+
);
|
|
50
|
+
expect(screen.getByTestId("checkbox-group")).not.toHaveAttribute(
|
|
51
|
+
"aria-label",
|
|
52
|
+
"Test Label"
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
rerender(
|
|
56
|
+
<CheckboxGroup labelText="Test Label" name="test2" showLabel={false}>
|
|
57
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
58
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
59
|
+
<Checkbox value="4" labelText="Checkbox 4" />
|
|
60
|
+
</CheckboxGroup>
|
|
61
|
+
);
|
|
62
|
+
expect(screen.getByTestId("checkbox-group")).toHaveAttribute(
|
|
63
|
+
"aria-label",
|
|
64
|
+
"Test Label"
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("renders visible helper or error text", () => {
|
|
69
|
+
const { rerender } = render(
|
|
70
|
+
<CheckboxGroup
|
|
71
|
+
labelText="Test Label"
|
|
72
|
+
name="test3"
|
|
73
|
+
helperText="This is the helper text for the full group."
|
|
74
|
+
invalidText="This is the error text :("
|
|
75
|
+
>
|
|
76
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
77
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
78
|
+
<Checkbox value="4" labelText="Checkbox 4" />
|
|
79
|
+
</CheckboxGroup>
|
|
80
|
+
);
|
|
81
|
+
expect(
|
|
82
|
+
screen.getByText("This is the helper text for the full group.")
|
|
83
|
+
).toBeVisible();
|
|
84
|
+
expect(
|
|
85
|
+
screen.queryByText("This is the error text :(")
|
|
86
|
+
).not.toBeInTheDocument();
|
|
87
|
+
|
|
88
|
+
rerender(
|
|
89
|
+
<CheckboxGroup
|
|
90
|
+
labelText="Test Label"
|
|
91
|
+
name="test3"
|
|
92
|
+
helperText="This is the helper text for the full group."
|
|
93
|
+
invalidText="This is the error text :("
|
|
94
|
+
isInvalid
|
|
95
|
+
>
|
|
96
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
97
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
98
|
+
<Checkbox value="4" labelText="Checkbox 4" />
|
|
99
|
+
</CheckboxGroup>
|
|
100
|
+
);
|
|
101
|
+
expect(screen.getByText("This is the error text :(")).toBeVisible();
|
|
102
|
+
expect(
|
|
103
|
+
screen.queryByText("This is the helper text for the full group.")
|
|
104
|
+
).not.toBeInTheDocument();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("sets the CheckboxGroup's ID", () => {
|
|
108
|
+
render(
|
|
109
|
+
<CheckboxGroup labelText="Test Label" name="test5" id="some-id">
|
|
110
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
111
|
+
</CheckboxGroup>
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// The "group" role here is for the `fieldset` element.
|
|
115
|
+
expect(screen.getByRole("group")).toHaveAttribute(
|
|
116
|
+
"id",
|
|
117
|
+
"checkbox-group-some-id"
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("sets the next value through the onChange function", () => {
|
|
122
|
+
let newValue = [];
|
|
123
|
+
const onChange = (value) => {
|
|
124
|
+
newValue = value;
|
|
125
|
+
};
|
|
126
|
+
render(
|
|
127
|
+
<CheckboxGroup
|
|
128
|
+
labelText="Test Label"
|
|
129
|
+
name="getValue"
|
|
130
|
+
defaultValue={["4"]}
|
|
131
|
+
onChange={onChange}
|
|
132
|
+
>
|
|
133
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
134
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
135
|
+
<Checkbox value="4" labelText="Checkbox 4" />
|
|
136
|
+
</CheckboxGroup>
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
expect(newValue).toEqual([]);
|
|
140
|
+
|
|
141
|
+
userEvent.click(screen.getByText("Checkbox 3"));
|
|
142
|
+
// "4" was the initial selected value
|
|
143
|
+
expect(newValue).toEqual(["4", "3"]);
|
|
144
|
+
userEvent.click(screen.getByText("Checkbox 2"));
|
|
145
|
+
expect(newValue).toEqual(["4", "3", "2"]);
|
|
146
|
+
userEvent.click(screen.getByText("Checkbox 3"));
|
|
147
|
+
expect(newValue).toEqual(["4", "2"]);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("calls the UUID generation function if no id prop value is passed", () => {
|
|
151
|
+
const generateUUIDSpy = jest.spyOn(generateUUID, "default");
|
|
152
|
+
expect(generateUUIDSpy).toHaveBeenCalledTimes(0);
|
|
153
|
+
render(
|
|
154
|
+
<CheckboxGroup labelText="Test Label" name="test6">
|
|
155
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
156
|
+
</CheckboxGroup>
|
|
157
|
+
);
|
|
158
|
+
expect(generateUUIDSpy).toHaveBeenCalledTimes(1);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("sets the 'disabled' attribute for all its Checkbox children", () => {
|
|
162
|
+
render(
|
|
163
|
+
<CheckboxGroup labelText="Test Label" name="test7" isDisabled>
|
|
164
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
165
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
166
|
+
<Checkbox value="4" labelText="Checkbox 4" />
|
|
167
|
+
</CheckboxGroup>
|
|
168
|
+
);
|
|
169
|
+
const Checkboxes = screen.getAllByRole("checkbox");
|
|
170
|
+
|
|
171
|
+
expect(Checkboxes).toHaveLength(3);
|
|
172
|
+
expect(Checkboxes[0]).toHaveAttribute("disabled");
|
|
173
|
+
expect(Checkboxes[1]).toHaveAttribute("disabled");
|
|
174
|
+
expect(Checkboxes[2]).toHaveAttribute("disabled");
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("sets the 'required' attribute for all its Checkbox children", () => {
|
|
178
|
+
render(
|
|
179
|
+
<CheckboxGroup labelText="Test Label" name="test8" isRequired>
|
|
180
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
181
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
182
|
+
<Checkbox value="4" labelText="Checkbox 4" />
|
|
183
|
+
</CheckboxGroup>
|
|
184
|
+
);
|
|
185
|
+
const Checkboxes = screen.getAllByRole("checkbox");
|
|
186
|
+
|
|
187
|
+
expect(Checkboxes).toHaveLength(3);
|
|
188
|
+
expect(Checkboxes[0]).toHaveAttribute("required");
|
|
189
|
+
expect(Checkboxes[1]).toHaveAttribute("required");
|
|
190
|
+
expect(Checkboxes[2]).toHaveAttribute("required");
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("sets the error state for all its Checkbox children", () => {
|
|
194
|
+
render(
|
|
195
|
+
<CheckboxGroup labelText="Test Label" name="test9" isInvalid>
|
|
196
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
197
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
198
|
+
<Checkbox value="4" labelText="Checkbox 4" />
|
|
199
|
+
</CheckboxGroup>
|
|
200
|
+
);
|
|
201
|
+
const Checkboxes = screen.getAllByRole("checkbox");
|
|
202
|
+
|
|
203
|
+
expect(Checkboxes).toHaveLength(3);
|
|
204
|
+
expect(Checkboxes[0]).toHaveAttribute("aria-invalid");
|
|
205
|
+
expect(Checkboxes[1]).toHaveAttribute("aria-invalid");
|
|
206
|
+
expect(Checkboxes[2]).toHaveAttribute("aria-invalid");
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it("renders the UI snapshot correctly", () => {
|
|
210
|
+
const column = renderer
|
|
211
|
+
.create(
|
|
212
|
+
<CheckboxGroup labelText="column" name="column" id="column">
|
|
213
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
214
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
215
|
+
</CheckboxGroup>
|
|
216
|
+
)
|
|
217
|
+
.toJSON();
|
|
218
|
+
const row = renderer
|
|
219
|
+
.create(
|
|
220
|
+
<CheckboxGroup
|
|
221
|
+
labelText="row"
|
|
222
|
+
name="row"
|
|
223
|
+
id="row"
|
|
224
|
+
layout={CheckboxGroupLayoutTypes.Row}
|
|
225
|
+
>
|
|
226
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
227
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
228
|
+
</CheckboxGroup>
|
|
229
|
+
)
|
|
230
|
+
.toJSON();
|
|
231
|
+
const noLabel = renderer
|
|
232
|
+
.create(
|
|
233
|
+
<CheckboxGroup
|
|
234
|
+
labelText="no label"
|
|
235
|
+
name="noLabel"
|
|
236
|
+
id="noLabel"
|
|
237
|
+
showLabel={false}
|
|
238
|
+
>
|
|
239
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
240
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
241
|
+
</CheckboxGroup>
|
|
242
|
+
)
|
|
243
|
+
.toJSON();
|
|
244
|
+
const helperText = renderer
|
|
245
|
+
.create(
|
|
246
|
+
<CheckboxGroup
|
|
247
|
+
labelText="helperText"
|
|
248
|
+
name="helperText"
|
|
249
|
+
id="helperText"
|
|
250
|
+
helperText="helper text"
|
|
251
|
+
>
|
|
252
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
253
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
254
|
+
</CheckboxGroup>
|
|
255
|
+
)
|
|
256
|
+
.toJSON();
|
|
257
|
+
const invalidText = renderer
|
|
258
|
+
.create(
|
|
259
|
+
<CheckboxGroup
|
|
260
|
+
labelText="invalidText"
|
|
261
|
+
name="invalidText"
|
|
262
|
+
id="invalidText"
|
|
263
|
+
invalidText="error text"
|
|
264
|
+
>
|
|
265
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
266
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
267
|
+
</CheckboxGroup>
|
|
268
|
+
)
|
|
269
|
+
.toJSON();
|
|
270
|
+
const noOptReqLabel = renderer
|
|
271
|
+
.create(
|
|
272
|
+
<CheckboxGroup
|
|
273
|
+
labelText="no optional or required label"
|
|
274
|
+
name="optReq"
|
|
275
|
+
id="optReq"
|
|
276
|
+
optReqFlag={false}
|
|
277
|
+
>
|
|
278
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
279
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
280
|
+
</CheckboxGroup>
|
|
281
|
+
)
|
|
282
|
+
.toJSON();
|
|
283
|
+
const isRequired = renderer
|
|
284
|
+
.create(
|
|
285
|
+
<CheckboxGroup
|
|
286
|
+
labelText="required"
|
|
287
|
+
name="required"
|
|
288
|
+
id="required"
|
|
289
|
+
isRequired
|
|
290
|
+
>
|
|
291
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
292
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
293
|
+
</CheckboxGroup>
|
|
294
|
+
)
|
|
295
|
+
.toJSON();
|
|
296
|
+
const isInvalid = renderer
|
|
297
|
+
.create(
|
|
298
|
+
<CheckboxGroup
|
|
299
|
+
labelText="invalid"
|
|
300
|
+
name="invalid"
|
|
301
|
+
id="invalid"
|
|
302
|
+
isInvalid
|
|
303
|
+
>
|
|
304
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
305
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
306
|
+
</CheckboxGroup>
|
|
307
|
+
)
|
|
308
|
+
.toJSON();
|
|
309
|
+
const isDisabled = renderer
|
|
310
|
+
.create(
|
|
311
|
+
<CheckboxGroup
|
|
312
|
+
labelText="disabled"
|
|
313
|
+
name="disabled"
|
|
314
|
+
id="disabled"
|
|
315
|
+
isDisabled
|
|
316
|
+
>
|
|
317
|
+
<Checkbox value="2" labelText="Checkbox 2" />
|
|
318
|
+
<Checkbox value="3" labelText="Checkbox 3" />
|
|
319
|
+
</CheckboxGroup>
|
|
320
|
+
)
|
|
321
|
+
.toJSON();
|
|
322
|
+
|
|
323
|
+
expect(column).toMatchSnapshot();
|
|
324
|
+
expect(row).toMatchSnapshot();
|
|
325
|
+
expect(noLabel).toMatchSnapshot();
|
|
326
|
+
expect(helperText).toMatchSnapshot();
|
|
327
|
+
expect(invalidText).toMatchSnapshot();
|
|
328
|
+
expect(noOptReqLabel).toMatchSnapshot();
|
|
329
|
+
expect(isRequired).toMatchSnapshot();
|
|
330
|
+
expect(isInvalid).toMatchSnapshot();
|
|
331
|
+
expect(isDisabled).toMatchSnapshot();
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it("should throw warning when a non-Checkbox component is used as a child", () => {
|
|
335
|
+
const warn = jest.spyOn(console, "warn");
|
|
336
|
+
render(
|
|
337
|
+
<CheckboxGroup labelText="wrong child!" name="wrong" id="wrong-child">
|
|
338
|
+
<p>This is wrong!</p>
|
|
339
|
+
</CheckboxGroup>
|
|
340
|
+
);
|
|
341
|
+
expect(warn).toHaveBeenCalledWith(
|
|
342
|
+
"Only `Checkbox` components are allowed inside the `CheckboxGroup` component."
|
|
343
|
+
);
|
|
344
|
+
});
|
|
345
|
+
});
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Box,
|
|
4
|
+
Stack,
|
|
5
|
+
CheckboxGroup as ChakraCheckboxGroup,
|
|
6
|
+
useMultiStyleConfig,
|
|
7
|
+
} from "@chakra-ui/react";
|
|
8
|
+
|
|
9
|
+
import HelperErrorText from "../HelperErrorText/HelperErrorText";
|
|
10
|
+
import generateUUID from "../../helpers/generateUUID";
|
|
11
|
+
import { spacing } from "../../theme/foundations/spacing";
|
|
12
|
+
import { CheckboxGroupLayoutTypes } from "./CheckboxGroupLayoutTypes";
|
|
13
|
+
import Checkbox from "../Checkbox/Checkbox";
|
|
14
|
+
|
|
15
|
+
export interface CheckboxGroupProps {
|
|
16
|
+
/** Any child node passed to the component. */
|
|
17
|
+
children: React.ReactNode;
|
|
18
|
+
/** Populates the initial value of the input */
|
|
19
|
+
defaultValue?: string[];
|
|
20
|
+
/** Optional string to populate the HelperErrorText for error state */
|
|
21
|
+
invalidText?: string;
|
|
22
|
+
/** Optional string to populate the HelperErrorText for standard state */
|
|
23
|
+
helperText?: string;
|
|
24
|
+
/** ID that other components can cross reference for accessibility purposes */
|
|
25
|
+
id?: string;
|
|
26
|
+
/** Adds the 'disabled' prop to the input when true. */
|
|
27
|
+
isDisabled?: boolean;
|
|
28
|
+
/** A`dds the 'aria-invalid' attribute to the input and
|
|
29
|
+
* sets the error state when true. */
|
|
30
|
+
isInvalid?: boolean;
|
|
31
|
+
/** Adds the 'required' attribute to the input when true. */
|
|
32
|
+
isRequired?: boolean;
|
|
33
|
+
/** The checkbox group label displayed in a `legend` element if `showlabel` is
|
|
34
|
+
* true, or an "aria-label" if `showLabel` is false. */
|
|
35
|
+
labelText: string;
|
|
36
|
+
/** Renders the checkbox buttons in a row or column (default). */
|
|
37
|
+
layout?: CheckboxGroupLayoutTypes;
|
|
38
|
+
/** The `name` prop indicates the form group for all the `Checkbox` children. */
|
|
39
|
+
name: string;
|
|
40
|
+
/** The action to perform on the `<input>`'s onChange function */
|
|
41
|
+
onChange?: (value: string[]) => void;
|
|
42
|
+
/** Whether or not to display "Required"/"Optional" in the label text. */
|
|
43
|
+
optReqFlag?: boolean;
|
|
44
|
+
/** Offers the ability to show the group's legend onscreen or hide it. Refer
|
|
45
|
+
* to the `labelText` property for more information. */
|
|
46
|
+
showLabel?: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const noop = () => {};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Wrapper component to wrap `Checkbox` components. Can be displayed in a
|
|
53
|
+
* column or in a row. The `CheckboxGroup` component renders all the necessary
|
|
54
|
+
* wrapping and associated text elements, but the checkbox input elements
|
|
55
|
+
* _need_ to be child `Checkbox` components from the NYPL Design System.
|
|
56
|
+
*/
|
|
57
|
+
const CheckboxGroup = React.forwardRef<HTMLInputElement, CheckboxGroupProps>(
|
|
58
|
+
(props, ref?) => {
|
|
59
|
+
const {
|
|
60
|
+
children,
|
|
61
|
+
defaultValue = [],
|
|
62
|
+
invalidText,
|
|
63
|
+
helperText,
|
|
64
|
+
id = generateUUID(),
|
|
65
|
+
isDisabled = false,
|
|
66
|
+
isInvalid = false,
|
|
67
|
+
isRequired = false,
|
|
68
|
+
labelText,
|
|
69
|
+
layout = CheckboxGroupLayoutTypes.Column,
|
|
70
|
+
name,
|
|
71
|
+
onChange,
|
|
72
|
+
optReqFlag = true,
|
|
73
|
+
showLabel = true,
|
|
74
|
+
} = props;
|
|
75
|
+
const footnote = isInvalid ? invalidText : helperText;
|
|
76
|
+
const spacingProp =
|
|
77
|
+
layout === CheckboxGroupLayoutTypes.Column ? spacing.s : spacing.l;
|
|
78
|
+
const newChildren = [];
|
|
79
|
+
const checkboxProps =
|
|
80
|
+
defaultValue && onChange
|
|
81
|
+
? {
|
|
82
|
+
defaultValue,
|
|
83
|
+
onChange,
|
|
84
|
+
}
|
|
85
|
+
: {};
|
|
86
|
+
|
|
87
|
+
// Go through the Checkbox children and update them as needed.
|
|
88
|
+
React.Children.map(children, (child: React.ReactElement, i) => {
|
|
89
|
+
if (child.type !== Checkbox) {
|
|
90
|
+
// Special case for Storybook MDX documentation.
|
|
91
|
+
if (child.props.mdxType && child.props.mdxType === "Checkbox") {
|
|
92
|
+
noop();
|
|
93
|
+
} else {
|
|
94
|
+
console.warn(
|
|
95
|
+
"Only `Checkbox` components are allowed inside the `CheckboxGroup` component."
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (child !== undefined && child !== null) {
|
|
101
|
+
const newProps = {
|
|
102
|
+
key: i,
|
|
103
|
+
id: `${id}-${i}`,
|
|
104
|
+
name,
|
|
105
|
+
isDisabled,
|
|
106
|
+
isInvalid,
|
|
107
|
+
isRequired,
|
|
108
|
+
};
|
|
109
|
+
newChildren.push(React.cloneElement(child, newProps));
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Get the Chakra-based styles for all the custom elements in this component.
|
|
114
|
+
const styles = useMultiStyleConfig("CustomCheckboxGroup", {});
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<Box as="fieldset" id={`checkbox-group-${id}`} __css={styles}>
|
|
118
|
+
<legend className={showLabel ? "" : "sr-only"}>
|
|
119
|
+
<span>{labelText}</span>
|
|
120
|
+
{optReqFlag && (
|
|
121
|
+
<Box as="span" __css={styles.required}>
|
|
122
|
+
{isRequired ? "Required" : "Optional"}
|
|
123
|
+
</Box>
|
|
124
|
+
)}
|
|
125
|
+
</legend>
|
|
126
|
+
<ChakraCheckboxGroup {...checkboxProps}>
|
|
127
|
+
<Stack
|
|
128
|
+
id={id}
|
|
129
|
+
data-testid="checkbox-group"
|
|
130
|
+
direction={[layout]}
|
|
131
|
+
spacing={spacingProp}
|
|
132
|
+
ref={ref}
|
|
133
|
+
aria-label={!showLabel ? labelText : null}
|
|
134
|
+
>
|
|
135
|
+
{newChildren}
|
|
136
|
+
</Stack>
|
|
137
|
+
</ChakraCheckboxGroup>
|
|
138
|
+
{footnote && (
|
|
139
|
+
<Box __css={styles.helper}>
|
|
140
|
+
<HelperErrorText isError={isInvalid}>{footnote}</HelperErrorText>
|
|
141
|
+
</Box>
|
|
142
|
+
)}
|
|
143
|
+
</Box>
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
export default CheckboxGroup;
|