@nypl/design-system-react-components 0.25.9 → 0.25.12
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 +96 -0
- package/README.md +4 -16
- package/dist/components/Breadcrumbs/BreadcrumbsTypes.d.ts +1 -0
- package/dist/components/DatePicker/DatePicker.d.ts +1 -1
- package/dist/components/Fieldset/Fieldset.d.ts +1 -3
- package/dist/components/Form/Form.d.ts +13 -12
- package/dist/components/Form/FormTypes.d.ts +2 -2
- package/dist/components/HorizontalRule/HorizontalRule.d.ts +1 -1
- package/dist/components/Icons/IconTypes.d.ts +9 -7
- package/dist/components/List/List.d.ts +1 -1
- package/dist/components/Logo/LogoSvgs.d.ts +23 -1
- package/dist/components/Logo/LogoTypes.d.ts +23 -1
- package/dist/components/Notification/Notification.d.ts +2 -0
- package/dist/components/Pagination/Pagination.d.ts +6 -2
- package/dist/components/RadioGroup/RadioGroup.d.ts +3 -3
- package/dist/components/SearchBar/SearchBar.d.ts +6 -6
- package/dist/components/Select/Select.d.ts +4 -0
- package/dist/components/Table/Table.d.ts +9 -3
- package/dist/components/Template/Template.d.ts +24 -5
- package/dist/design-system-react-components.cjs.development.js +2063 -548
- 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 +2056 -554
- package/dist/design-system-react-components.esm.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/resources.scss +0 -2
- package/dist/styles.css +1 -1
- package/dist/theme/components/breadcrumb.d.ts +4 -1
- package/dist/theme/components/checkbox.d.ts +0 -2
- package/dist/theme/components/customTable.d.ts +12 -3
- package/dist/theme/components/fieldset.d.ts +2 -0
- package/dist/theme/components/global.d.ts +15 -14
- package/dist/theme/components/globalMixins.d.ts +8 -8
- package/dist/theme/components/list.d.ts +6 -0
- package/dist/theme/components/notification.d.ts +16 -4
- package/dist/theme/components/radio.d.ts +3 -2
- package/dist/theme/components/searchBar.d.ts +4 -0
- package/dist/theme/components/select.d.ts +2 -9
- package/dist/theme/components/slider.d.ts +8 -4
- package/dist/theme/components/structuredContent.d.ts +9 -9
- package/dist/theme/components/textInput.d.ts +10 -12
- package/dist/theme/components/toggle.d.ts +6 -2
- package/dist/theme/foundations/global.d.ts +31 -3
- package/dist/utils/utils.d.ts +10 -0
- package/package.json +40 -36
- package/src/components/Accordion/Accordion.stories.mdx +1 -1
- package/src/components/Accordion/Accordion.test.tsx +45 -1
- package/src/components/Accordion/Accordion.tsx +20 -8
- package/src/components/Accordion/__snapshots__/Accordion.test.tsx.snap +243 -0
- package/src/components/Breadcrumbs/Breadcrumbs.stories.mdx +30 -2
- package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +25 -0
- package/src/components/Breadcrumbs/Breadcrumbs.tsx +9 -3
- package/src/components/Breadcrumbs/BreadcrumbsTypes.tsx +1 -0
- package/src/components/Breadcrumbs/__snapshots__/Breadcrumbs.test.tsx.snap +104 -5
- package/src/components/Card/Card.stories.mdx +1 -1
- package/src/components/Card/Card.tsx +4 -1
- package/src/components/Card/__snapshots__/Card.test.tsx.snap +1 -1
- package/src/components/Chakra/Flex.stories.mdx +113 -0
- package/src/components/Checkbox/Checkbox.stories.mdx +1 -1
- package/src/components/Checkbox/Checkbox.tsx +1 -0
- package/src/components/Checkbox/__snapshots__/Checkbox.test.tsx.snap +6 -6
- package/src/components/CheckboxGroup/CheckboxGroup.stories.mdx +1 -1
- package/src/components/CheckboxGroup/__snapshots__/CheckboxGroup.test.tsx.snap +18 -18
- package/src/components/DatePicker/DatePicker.stories.mdx +1 -1
- package/src/components/DatePicker/DatePicker.test.tsx +6 -6
- package/src/components/DatePicker/DatePicker.tsx +12 -10
- package/src/components/DatePicker/__snapshots__/DatePicker.test.tsx.snap +28 -20
- package/src/components/Fieldset/Fieldset.stories.mdx +1 -1
- package/src/components/Fieldset/Fieldset.tsx +2 -4
- package/src/components/Form/Form.stories.mdx +34 -16
- package/src/components/Form/Form.test.tsx +92 -3
- package/src/components/Form/Form.tsx +25 -21
- package/src/components/Form/FormTypes.tsx +2 -2
- package/src/components/Form/__snapshots__/Form.test.tsx.snap +0 -1
- package/src/components/HelperErrorText/HelperErrorText.stories.mdx +1 -1
- package/src/components/Hero/Hero.stories.mdx +1 -1
- package/src/components/HorizontalRule/HorizontalRule.stories.mdx +3 -2
- package/src/components/HorizontalRule/HorizontalRule.tsx +2 -2
- package/src/components/HorizontalRule/__snapshots__/HorizontalRule.test.tsx.snap +4 -4
- package/src/components/Icons/Icon.stories.mdx +1 -1
- package/src/components/Icons/Icon.test.tsx +1 -1
- package/src/components/Icons/Icon.tsx +1 -1
- package/src/components/Icons/IconTypes.tsx +8 -6
- package/src/components/List/List.stories.mdx +24 -5
- package/src/components/List/List.test.tsx +1 -1
- package/src/components/List/List.tsx +2 -2
- package/src/components/List/__snapshots__/List.test.tsx.snap +3 -1
- package/src/components/Logo/Logo.stories.mdx +7 -5
- package/src/components/Logo/LogoSvgs.tsx +45 -1
- package/src/components/Logo/LogoTypes.tsx +22 -0
- package/src/components/Notification/Notification.stories.mdx +73 -1
- package/src/components/Notification/Notification.test.tsx +64 -5
- package/src/components/Notification/Notification.tsx +21 -11
- package/src/components/Notification/__snapshots__/Notification.test.tsx.snap +103 -8
- package/src/components/Pagination/Pagination.stories.mdx +54 -12
- package/src/components/Pagination/Pagination.test.tsx +63 -5
- package/src/components/Pagination/Pagination.tsx +46 -24
- package/src/components/Pagination/__snapshots__/Pagination.test.tsx.snap +3 -3
- package/src/components/Radio/Radio.stories.mdx +1 -1
- package/src/components/Radio/Radio.tsx +1 -0
- package/src/components/Radio/__snapshots__/Radio.test.tsx.snap +5 -5
- package/src/components/RadioGroup/RadioGroup.stories.mdx +1 -1
- package/src/components/RadioGroup/RadioGroup.test.tsx +13 -11
- package/src/components/RadioGroup/RadioGroup.tsx +88 -89
- package/src/components/RadioGroup/__snapshots__/RadioGroup.test.tsx.snap +18 -18
- package/src/components/SearchBar/SearchBar.Test.tsx +124 -28
- package/src/components/SearchBar/SearchBar.stories.mdx +9 -6
- package/src/components/SearchBar/SearchBar.tsx +24 -23
- package/src/components/Select/Select.stories.mdx +1 -1
- package/src/components/Select/Select.test.tsx +89 -0
- package/src/components/Select/Select.tsx +11 -2
- package/src/components/Select/__snapshots__/Select.test.tsx.snap +545 -0
- package/src/components/Slider/Slider.stories.mdx +1 -1
- package/src/components/Slider/Slider.tsx +4 -1
- package/src/components/Slider/__snapshots__/Slider.test.tsx.snap +7 -0
- package/src/components/StructuredContent/StructuredContent.stories.mdx +1 -1
- package/src/components/StyleGuide/Bidirectionality.stories.mdx +4 -4
- package/src/components/StyleGuide/Colors.stories.mdx +33 -18
- package/src/components/Table/Table.stories.mdx +118 -19
- package/src/components/Table/Table.test.tsx +80 -3
- package/src/components/Table/Table.tsx +26 -16
- package/src/components/Table/__snapshots__/Table.test.tsx.snap +1179 -0
- package/src/components/Tabs/Tabs.stories.mdx +1 -1
- package/src/components/Tabs/Tabs.test.tsx +21 -5
- package/src/components/Tabs/Tabs.tsx +35 -20
- package/src/components/Tabs/__snapshots__/Tabs.test.tsx.snap +195 -0
- package/src/components/Template/Template.stories.mdx +79 -4
- package/src/components/Template/Template.test.tsx +65 -3
- package/src/components/Template/Template.tsx +60 -14
- package/src/components/Template/__snapshots__/Template.test.tsx.snap +94 -1
- package/src/components/TextInput/TextInput.stories.mdx +1 -1
- package/src/components/Toggle/Toggle.stories.mdx +1 -1
- package/src/components/Toggle/Toggle.tsx +2 -1
- package/src/components/Toggle/__snapshots__/Toggle.test.tsx.snap +4 -4
- package/src/docs/Chakra.stories.mdx +1 -1
- package/src/index.ts +8 -2
- package/src/styles/base/_place-holder.scss +2 -0
- package/src/styles.scss +0 -2
- package/src/theme/components/breadcrumb.ts +5 -1
- package/src/theme/components/checkbox.ts +3 -7
- package/src/theme/components/customTable.ts +16 -3
- package/src/theme/components/fieldset.ts +2 -0
- package/src/theme/components/global.ts +19 -16
- package/src/theme/components/globalMixins.ts +8 -8
- package/src/theme/components/list.ts +6 -2
- package/src/theme/components/notification.ts +21 -8
- package/src/theme/components/radio.ts +3 -6
- package/src/theme/components/searchBar.ts +4 -0
- package/src/theme/components/select.ts +3 -3
- package/src/theme/components/slider.ts +12 -9
- package/src/theme/components/structuredContent.ts +26 -6
- package/src/theme/components/textInput.ts +3 -2
- package/src/theme/components/toggle.ts +42 -38
- package/src/theme/foundations/colors.ts +19 -12
- package/src/theme/foundations/global.ts +17 -5
- package/src/theme/foundations/typography.ts +2 -2
- package/src/utils/componentCategories.ts +2 -1
- package/src/utils/utils.ts +28 -0
- package/dist/components/Pagination/Pagination.stories.d.ts +0 -13
- package/src/components/Pagination/Pagination.stories.tsx +0 -54
- package/src/styles/base/_03-base.scss +0 -25
- package/src/styles/base/_04-focus.scss +0 -22
|
@@ -433,17 +433,21 @@ exports[`DatePicker Date Range renders the UI snapshot correctly 4`] = `
|
|
|
433
433
|
</div>
|
|
434
434
|
</div>
|
|
435
435
|
<div
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
436
|
+
className="css-fjhuh4"
|
|
437
|
+
>
|
|
438
|
+
<div
|
|
439
|
+
aria-atomic={true}
|
|
440
|
+
aria-live="off"
|
|
441
|
+
className=" css-0"
|
|
442
|
+
dangerouslySetInnerHTML={
|
|
443
|
+
Object {
|
|
444
|
+
"__html": "Note that the Library may be closed on Sundays.",
|
|
445
|
+
}
|
|
442
446
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
+
data-isinvalid={false}
|
|
448
|
+
id="invalid-helper-text"
|
|
449
|
+
/>
|
|
450
|
+
</div>
|
|
447
451
|
</fieldset>
|
|
448
452
|
</div>
|
|
449
453
|
`;
|
|
@@ -545,17 +549,21 @@ exports[`DatePicker Date Range renders the UI snapshot correctly 5`] = `
|
|
|
545
549
|
</div>
|
|
546
550
|
</div>
|
|
547
551
|
<div
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
552
|
+
className="css-fjhuh4"
|
|
553
|
+
>
|
|
554
|
+
<div
|
|
555
|
+
aria-atomic={true}
|
|
556
|
+
aria-live="off"
|
|
557
|
+
className=" css-0"
|
|
558
|
+
dangerouslySetInnerHTML={
|
|
559
|
+
Object {
|
|
560
|
+
"__html": "Note that the Library may be closed on Sundays.",
|
|
561
|
+
}
|
|
554
562
|
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
563
|
+
data-isinvalid={false}
|
|
564
|
+
id="disabled-helper-text"
|
|
565
|
+
/>
|
|
566
|
+
</div>
|
|
559
567
|
</fieldset>
|
|
560
568
|
</div>
|
|
561
569
|
`;
|
|
@@ -2,8 +2,6 @@ import React from "react";
|
|
|
2
2
|
import { Box, useMultiStyleConfig } from "@chakra-ui/react";
|
|
3
3
|
|
|
4
4
|
interface FieldsetProps {
|
|
5
|
-
/** Children to render. Typically form-related components are used. */
|
|
6
|
-
children: React.ReactNode;
|
|
7
5
|
/** Additional class name to add. */
|
|
8
6
|
className?: string;
|
|
9
7
|
/** ID that other components can cross reference for accessibility purposes */
|
|
@@ -24,7 +22,7 @@ interface FieldsetProps {
|
|
|
24
22
|
* A wrapper component that renders a `fieldset` element along with a `legend`
|
|
25
23
|
* element as its first child. Commonly used to wrap form components.
|
|
26
24
|
*/
|
|
27
|
-
const Fieldset
|
|
25
|
+
const Fieldset = ({
|
|
28
26
|
children,
|
|
29
27
|
className,
|
|
30
28
|
id,
|
|
@@ -32,7 +30,7 @@ const Fieldset: React.FC<FieldsetProps> = ({
|
|
|
32
30
|
isRequired = false,
|
|
33
31
|
legendText,
|
|
34
32
|
optReqFlag = true,
|
|
35
|
-
}) => {
|
|
33
|
+
}: React.PropsWithChildren<FieldsetProps>) => {
|
|
36
34
|
const styles = useMultiStyleConfig("Fieldset", { isLegendHidden });
|
|
37
35
|
return (
|
|
38
36
|
<Box as="fieldset" id={id} __css={styles} className={className}>
|
|
@@ -14,7 +14,7 @@ import CheckboxGroup from "../CheckboxGroup/CheckboxGroup";
|
|
|
14
14
|
import DatePicker from "../DatePicker/DatePicker";
|
|
15
15
|
import { DatePickerTypes } from "../DatePicker/DatePickerTypes";
|
|
16
16
|
import Form, { FormRow, FormField } from "./Form";
|
|
17
|
-
import {
|
|
17
|
+
import { FormGaps } from "./FormTypes";
|
|
18
18
|
import Heading from "../Heading/Heading";
|
|
19
19
|
import { HeadingLevels } from "../Heading/HeadingTypes";
|
|
20
20
|
import HorizontalRule from "../HorizontalRule/HorizontalRule";
|
|
@@ -27,7 +27,7 @@ import { getCategory } from "../../utils/componentCategories";
|
|
|
27
27
|
import SimpleGrid from "../Grid/SimpleGrid";
|
|
28
28
|
import { getStorybookEnumValues } from "../../utils/utils";
|
|
29
29
|
|
|
30
|
-
export const enumValues = getStorybookEnumValues(
|
|
30
|
+
export const enumValues = getStorybookEnumValues(FormGaps, "FormGaps");
|
|
31
31
|
|
|
32
32
|
<Meta
|
|
33
33
|
title={getCategory("Form")}
|
|
@@ -47,9 +47,9 @@ export const enumValues = getStorybookEnumValues(FormSpacing, "FormSpacing");
|
|
|
47
47
|
control: { type: "radio" },
|
|
48
48
|
options: ["get", "post"],
|
|
49
49
|
},
|
|
50
|
-
|
|
50
|
+
gap: {
|
|
51
51
|
control: { type: "select" },
|
|
52
|
-
table: { defaultValue: { summary: "
|
|
52
|
+
table: { defaultValue: { summary: "FormGaps.Large" } },
|
|
53
53
|
options: enumValues.options,
|
|
54
54
|
},
|
|
55
55
|
}}
|
|
@@ -60,15 +60,31 @@ export const enumValues = getStorybookEnumValues(FormSpacing, "FormSpacing");
|
|
|
60
60
|
| Component Version | DS Version |
|
|
61
61
|
| ----------------- | ---------- |
|
|
62
62
|
| Added | `0.23.2` |
|
|
63
|
-
| Latest | `0.25.
|
|
63
|
+
| Latest | `0.25.10` |
|
|
64
64
|
|
|
65
65
|
<Description of={Form} />
|
|
66
66
|
|
|
67
|
-
The `Form` component renders a standard `<form>` element and should be used to
|
|
67
|
+
The `Form` component renders a standard `<form>` element and should be used to
|
|
68
|
+
handle layout and spacing for child input fields. `FormRow` and `FormField`
|
|
69
|
+
components should be used to build the `<form>` structure and to arrange input
|
|
70
|
+
fields as needed.
|
|
68
71
|
|
|
69
|
-
|
|
72
|
+
```jsx
|
|
73
|
+
<Form>
|
|
74
|
+
<FormRow>
|
|
75
|
+
<FormField>{/* ... */}</FormField>
|
|
76
|
+
</FormRow>
|
|
77
|
+
<FormRow>
|
|
78
|
+
<FormField>{/* ... */}</FormField>
|
|
79
|
+
</FormRow>
|
|
80
|
+
</Form>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`FormField` should be used as a parent for all input components from the DS
|
|
84
|
+
(`Button`, `Select`, `TextInput`, etc.).
|
|
70
85
|
|
|
71
|
-
`FormRow` should be used as a parent of multiple `FormField` components when you
|
|
86
|
+
`FormRow` should be used as a parent of multiple `FormField` components when you
|
|
87
|
+
need to render multiple input components in a horizontal row.
|
|
72
88
|
|
|
73
89
|
<Canvas withToolbar>
|
|
74
90
|
<Story
|
|
@@ -78,11 +94,11 @@ The `Form` component renders a standard `<form>` element and should be used to h
|
|
|
78
94
|
className: undefined,
|
|
79
95
|
id: "form-id",
|
|
80
96
|
method: "get",
|
|
81
|
-
|
|
97
|
+
gap: "FormGaps.Large",
|
|
82
98
|
}}
|
|
83
99
|
>
|
|
84
100
|
{(args) => (
|
|
85
|
-
<Form {...args}
|
|
101
|
+
<Form {...args} gap={enumValues.getValue(args.gap)}>
|
|
86
102
|
<FormRow>
|
|
87
103
|
<FormField>
|
|
88
104
|
<TextInput
|
|
@@ -205,7 +221,7 @@ export const formRow = (nameString, size) => {
|
|
|
205
221
|
return (
|
|
206
222
|
<li key={size}>
|
|
207
223
|
<Heading level={HeadingLevels.Three}>{labelText}</Heading>
|
|
208
|
-
<Form
|
|
224
|
+
<Form gap={size}>
|
|
209
225
|
<FormRow>
|
|
210
226
|
<FormField>
|
|
211
227
|
<Select
|
|
@@ -250,16 +266,18 @@ export const formRow = (nameString, size) => {
|
|
|
250
266
|
);
|
|
251
267
|
};
|
|
252
268
|
export const sizes = [];
|
|
253
|
-
for (const
|
|
254
|
-
sizes.push(formRow(`
|
|
269
|
+
for (const FormGaps in FormGaps) {
|
|
270
|
+
sizes.push(formRow(`FormGaps.${FormGaps}`, FormGaps[FormGaps]));
|
|
255
271
|
}
|
|
256
272
|
export const getForms = (list) => <ul style={{ listStyle: "none" }}>{list}</ul>;
|
|
257
273
|
|
|
258
|
-
By default, the `Form` component will handle the NYPL spacing around form input
|
|
274
|
+
By default, the `Form` component will handle the NYPL spacing around form input
|
|
275
|
+
elements. The default spacing value is `large`, which corresponds to the CSS
|
|
276
|
+
variable `--nypl-space-l` (2rem / 32px).
|
|
259
277
|
|
|
260
278
|
**IMPORTANT:** The default spacing should not be overwritten without a very good reason.
|
|
261
279
|
|
|
262
|
-
Below are the spacing variants available with the `
|
|
280
|
+
Below are the spacing variants available with the `FormGaps` enum.
|
|
263
281
|
|
|
264
282
|
<Canvas>
|
|
265
283
|
<Story
|
|
@@ -277,7 +295,7 @@ Below are the spacing variants available with the `FormSpacing` enum.
|
|
|
277
295
|
<Story name="Example Code" />
|
|
278
296
|
|
|
279
297
|
```jsx
|
|
280
|
-
<Form action="/end/point" method="get"
|
|
298
|
+
<Form action="/end/point" method="get" gap={FormGaps.Large}>
|
|
281
299
|
<FormField>
|
|
282
300
|
<TextInput
|
|
283
301
|
labelText="Username"
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
3
3
|
import { axe } from "jest-axe";
|
|
4
4
|
import renderer from "react-test-renderer";
|
|
5
5
|
|
|
6
6
|
import Form, { FormRow, FormField } from "./Form";
|
|
7
|
-
// import {
|
|
7
|
+
// import { FormGaps } from "./FormTypes";
|
|
8
8
|
import TextInput from "../TextInput/TextInput";
|
|
9
9
|
|
|
10
10
|
describe("Form Accessibility", () => {
|
|
@@ -12,6 +12,19 @@ describe("Form Accessibility", () => {
|
|
|
12
12
|
const { container } = render(<Form />);
|
|
13
13
|
expect(await axe(container)).toHaveNoViolations();
|
|
14
14
|
});
|
|
15
|
+
|
|
16
|
+
it("passes axe accessibility test for the full hierachy", async () => {
|
|
17
|
+
const { container } = render(
|
|
18
|
+
<Form>
|
|
19
|
+
<FormRow>
|
|
20
|
+
<FormField>Form Field 1</FormField>
|
|
21
|
+
<FormField>Form Field 2</FormField>
|
|
22
|
+
<FormField>Form Field 3</FormField>
|
|
23
|
+
</FormRow>
|
|
24
|
+
</Form>
|
|
25
|
+
);
|
|
26
|
+
expect(await axe(container)).toHaveNoViolations();
|
|
27
|
+
});
|
|
15
28
|
});
|
|
16
29
|
|
|
17
30
|
describe("Form Snapshot", () => {
|
|
@@ -101,11 +114,87 @@ describe("Form", () => {
|
|
|
101
114
|
expect(form).toHaveAttribute("method", "get");
|
|
102
115
|
});
|
|
103
116
|
|
|
117
|
+
it("passes down the `Form`'s id down to its children", () => {
|
|
118
|
+
const { container } = render(
|
|
119
|
+
<Form id="formId">
|
|
120
|
+
<FormRow>
|
|
121
|
+
<FormField>
|
|
122
|
+
<TextInput labelText="Input Field" />
|
|
123
|
+
</FormField>
|
|
124
|
+
<FormField>
|
|
125
|
+
<TextInput labelText="Input Field" />
|
|
126
|
+
</FormField>
|
|
127
|
+
</FormRow>
|
|
128
|
+
<FormRow>
|
|
129
|
+
<FormField>
|
|
130
|
+
<TextInput labelText="Input Field" />
|
|
131
|
+
</FormField>
|
|
132
|
+
<FormField>
|
|
133
|
+
<TextInput labelText="Input Field" />
|
|
134
|
+
</FormField>
|
|
135
|
+
</FormRow>
|
|
136
|
+
</Form>
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
expect(container.querySelector("#formId")).toBeInTheDocument();
|
|
140
|
+
// The first `FormRow` adds "child0" to its id
|
|
141
|
+
expect(container.querySelector("#formId-child0")).toBeInTheDocument();
|
|
142
|
+
// The first `FormRow`'s first `FormField` adds "grandchild0" to its id
|
|
143
|
+
expect(
|
|
144
|
+
container.querySelector("#formId-child0-grandchild0")
|
|
145
|
+
).toBeInTheDocument();
|
|
146
|
+
// The first `FormRow`'s second `FormField` adds "grandchild1" to its id
|
|
147
|
+
expect(
|
|
148
|
+
container.querySelector("#formId-child0-grandchild1")
|
|
149
|
+
).toBeInTheDocument();
|
|
150
|
+
// The second `FormRow` adds "child1" to its id
|
|
151
|
+
expect(container.querySelector("#formId-child1")).toBeInTheDocument();
|
|
152
|
+
// The second `FormRow`'s first `FormField` adds "grandchild0" to its id
|
|
153
|
+
expect(
|
|
154
|
+
container.querySelector("#formId-child1-grandchild0")
|
|
155
|
+
).toBeInTheDocument();
|
|
156
|
+
// The second `FormRow`'s second `FormField` adds "grandchild1" to its id
|
|
157
|
+
expect(
|
|
158
|
+
container.querySelector("#formId-child1-grandchild1")
|
|
159
|
+
).toBeInTheDocument();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("logs a warning if a child of `FormRow` is not a `FormField`", () => {
|
|
163
|
+
const warn = jest.spyOn(console, "warn");
|
|
164
|
+
render(
|
|
165
|
+
<Form>
|
|
166
|
+
<FormRow>
|
|
167
|
+
<div>Not a FormField</div>
|
|
168
|
+
</FormRow>
|
|
169
|
+
</Form>
|
|
170
|
+
);
|
|
171
|
+
expect(warn).toHaveBeenCalledWith(
|
|
172
|
+
"FormRow children must be `FormField` components."
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("calls the onSubmit function", () => {
|
|
177
|
+
const onSubmit = jest.fn();
|
|
178
|
+
render(
|
|
179
|
+
<Form onSubmit={onSubmit}>
|
|
180
|
+
<FormRow>
|
|
181
|
+
<FormField>
|
|
182
|
+
<TextInput labelText="Input Field" />
|
|
183
|
+
</FormField>
|
|
184
|
+
</FormRow>
|
|
185
|
+
</Form>
|
|
186
|
+
);
|
|
187
|
+
const form = screen.getByRole("form");
|
|
188
|
+
expect(onSubmit).toHaveBeenCalledTimes(0);
|
|
189
|
+
fireEvent.submit(form);
|
|
190
|
+
expect(onSubmit).toHaveBeenCalledTimes(1);
|
|
191
|
+
});
|
|
192
|
+
|
|
104
193
|
// TO DO: There's somethign weird about checking for the "grid-gap" style.
|
|
105
194
|
// Other styles can be validated, but "grid-gap" is being ellusive.
|
|
106
195
|
// it("Renders a <form> element with spacing variant applied", () => {
|
|
107
196
|
// render(
|
|
108
|
-
// <Form
|
|
197
|
+
// <Form gap={FormGaps.ExtraSmall}>
|
|
109
198
|
// <FormRow />
|
|
110
199
|
// </Form>
|
|
111
200
|
// );
|
|
@@ -1,30 +1,29 @@
|
|
|
1
|
-
import { Box } from "@chakra-ui/react";
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
|
|
4
|
-
import {
|
|
3
|
+
import { FormGaps } from "./FormTypes";
|
|
5
4
|
import SimpleGrid from "../Grid/SimpleGrid";
|
|
6
5
|
import generateUUID from "../../helpers/generateUUID";
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
/** className to be applied to FormRow */
|
|
7
|
+
interface FormBaseProps {
|
|
8
|
+
/** className to be applied to FormRow, FormField, and Form */
|
|
10
9
|
className?: string;
|
|
11
|
-
/**
|
|
12
|
-
|
|
10
|
+
/** Optional spacing size; if omitted, the default `large` (2rem / 32px)
|
|
11
|
+
* spacing will be used; ```IMPORTANT: for general form layout, this prop
|
|
12
|
+
* should not be used``` */
|
|
13
|
+
gap?: FormGaps;
|
|
13
14
|
/** ID that other components can cross reference (internal use) */
|
|
14
15
|
id?: string;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
export interface
|
|
18
|
+
export interface FormChildProps extends FormBaseProps {}
|
|
19
|
+
|
|
20
|
+
export interface FormProps extends FormBaseProps {
|
|
18
21
|
/** Optional form `action` attribute */
|
|
19
22
|
action?: string;
|
|
20
|
-
/** Optional className you can add in addition to `form` */
|
|
21
|
-
className?: string;
|
|
22
|
-
/** Optional ID that other components can cross reference */
|
|
23
|
-
id?: string;
|
|
24
23
|
/** Optional form `method` attribute */
|
|
25
24
|
method?: "get" | "post";
|
|
26
|
-
/**
|
|
27
|
-
|
|
25
|
+
/** Function to call for the `onSubmit` form event. */
|
|
26
|
+
onSubmit?: (e: React.FormEvent<HTMLFormElement>) => void;
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
/** FormRow child-component */
|
|
@@ -35,7 +34,11 @@ export function FormRow(props: React.PropsWithChildren<FormChildProps>) {
|
|
|
35
34
|
children,
|
|
36
35
|
(child: React.ReactElement, i) => {
|
|
37
36
|
if (!child) return null;
|
|
38
|
-
|
|
37
|
+
if (child.type === FormField || child.props.mdxType === "FormField") {
|
|
38
|
+
return React.cloneElement(child, { id: `${id}-grandchild${i}` });
|
|
39
|
+
}
|
|
40
|
+
console.warn("FormRow children must be `FormField` components.");
|
|
41
|
+
return null;
|
|
39
42
|
}
|
|
40
43
|
);
|
|
41
44
|
return (
|
|
@@ -61,9 +64,10 @@ export default function Form(props: React.PropsWithChildren<FormProps>) {
|
|
|
61
64
|
action,
|
|
62
65
|
children,
|
|
63
66
|
className,
|
|
67
|
+
gap = FormGaps.Large,
|
|
64
68
|
id = generateUUID(),
|
|
65
69
|
method,
|
|
66
|
-
|
|
70
|
+
onSubmit,
|
|
67
71
|
} = props;
|
|
68
72
|
|
|
69
73
|
let attributes = {};
|
|
@@ -76,21 +80,21 @@ export default function Form(props: React.PropsWithChildren<FormProps>) {
|
|
|
76
80
|
const alteredChildren = React.Children.map(
|
|
77
81
|
children,
|
|
78
82
|
(child: React.ReactElement, i) => {
|
|
79
|
-
return React.cloneElement(child, { gap
|
|
83
|
+
return React.cloneElement(child, { gap, id: `${id}-child${i}` });
|
|
80
84
|
}
|
|
81
85
|
);
|
|
82
86
|
|
|
83
87
|
return (
|
|
84
|
-
<
|
|
85
|
-
as="form"
|
|
88
|
+
<form
|
|
86
89
|
aria-label="form"
|
|
90
|
+
className={className}
|
|
87
91
|
id={id}
|
|
92
|
+
onSubmit={onSubmit}
|
|
88
93
|
{...attributes}
|
|
89
|
-
className={className}
|
|
90
94
|
>
|
|
91
|
-
<SimpleGrid columns={1} gap={
|
|
95
|
+
<SimpleGrid columns={1} gap={gap} id={`${id}-parent`}>
|
|
92
96
|
{alteredChildren}
|
|
93
97
|
</SimpleGrid>
|
|
94
|
-
</
|
|
98
|
+
</form>
|
|
95
99
|
);
|
|
96
100
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { GridGaps as
|
|
1
|
+
import { GridGaps as FormGaps } from "../Grid/GridTypes";
|
|
2
2
|
|
|
3
|
-
export {
|
|
3
|
+
export { FormGaps };
|
|
@@ -26,7 +26,7 @@ export const enumValues = getStorybookEnumValues(HeroTypes, "HeroTypes");
|
|
|
26
26
|
parameters={{
|
|
27
27
|
design: {
|
|
28
28
|
type: "figma",
|
|
29
|
-
url: "https://www.figma.com/file/qShodlfNCJHb8n03IFyApM/Main?node-id=
|
|
29
|
+
url: "https://www.figma.com/file/qShodlfNCJHb8n03IFyApM/Main?node-id=36817%3A23704",
|
|
30
30
|
},
|
|
31
31
|
jest: ["Hero.test.tsx"],
|
|
32
32
|
}}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import { withDesign } from "storybook-addon-designs";
|
|
10
10
|
|
|
11
11
|
import HorizontalRule from "./HorizontalRule";
|
|
12
|
+
import SimpleGrid from "../Grid/SimpleGrid";
|
|
12
13
|
import { getCategory } from "../../utils/componentCategories";
|
|
13
14
|
|
|
14
15
|
<Meta
|
|
@@ -25,7 +26,7 @@ import { getCategory } from "../../utils/componentCategories";
|
|
|
25
26
|
argTypes={{
|
|
26
27
|
className: { control: false },
|
|
27
28
|
height: { table: { defaultValue: { summary: "2px" } } },
|
|
28
|
-
width: { table: { defaultValue: { summary: "
|
|
29
|
+
width: { table: { defaultValue: { summary: "100%" } } },
|
|
29
30
|
}}
|
|
30
31
|
/>
|
|
31
32
|
|
|
@@ -34,7 +35,7 @@ import { getCategory } from "../../utils/componentCategories";
|
|
|
34
35
|
| Component Version | DS Version |
|
|
35
36
|
| ----------------- | ---------- |
|
|
36
37
|
| Added | `0.23.0` |
|
|
37
|
-
| Latest | `0.25.
|
|
38
|
+
| Latest | `0.25.10` |
|
|
38
39
|
|
|
39
40
|
<Description of={HorizontalRule} />
|
|
40
41
|
|
|
@@ -16,12 +16,12 @@ export interface HorizontalRuleProps {
|
|
|
16
16
|
height?: string;
|
|
17
17
|
/** Optional width value. This value should be entered with the same
|
|
18
18
|
* formatting as a CSS width attribute (ex. `50%`, `640px`, `20rem`). If
|
|
19
|
-
* omitted, the horizontal rule will have a default width of "
|
|
19
|
+
* omitted, the horizontal rule will have a default width of "100%". */
|
|
20
20
|
width?: string;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export default function HorizontalRule(props: HorizontalRuleProps) {
|
|
24
|
-
const { align, className, height = "2px", width = "
|
|
24
|
+
const { align, className, height = "2px", width = "100%" } = props;
|
|
25
25
|
const styles = useStyleConfig("HorizontalRule", { align });
|
|
26
26
|
let finalHeight = height;
|
|
27
27
|
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`HorizontalRule renders the UI snapshot correctly 1`] = `
|
|
4
4
|
<hr
|
|
5
|
-
className="css-
|
|
5
|
+
className="css-1bhbd2a"
|
|
6
6
|
/>
|
|
7
7
|
`;
|
|
8
8
|
|
|
9
9
|
exports[`HorizontalRule renders the UI snapshot correctly 2`] = `
|
|
10
10
|
<hr
|
|
11
|
-
className="css-
|
|
11
|
+
className="css-154goob"
|
|
12
12
|
/>
|
|
13
13
|
`;
|
|
14
14
|
|
|
@@ -20,12 +20,12 @@ exports[`HorizontalRule renders the UI snapshot correctly 3`] = `
|
|
|
20
20
|
|
|
21
21
|
exports[`HorizontalRule renders the UI snapshot correctly 4`] = `
|
|
22
22
|
<hr
|
|
23
|
-
className="css-
|
|
23
|
+
className="css-1bhbd2a"
|
|
24
24
|
/>
|
|
25
25
|
`;
|
|
26
26
|
|
|
27
27
|
exports[`HorizontalRule renders the UI snapshot correctly 5`] = `
|
|
28
28
|
<hr
|
|
29
|
-
className="css-
|
|
29
|
+
className="css-1bhbd2a"
|
|
30
30
|
/>
|
|
31
31
|
`;
|
|
@@ -35,7 +35,7 @@ describe("Icon", () => {
|
|
|
35
35
|
const warn = jest.spyOn(console, "warn");
|
|
36
36
|
render(<Icon />);
|
|
37
37
|
expect(warn).toHaveBeenCalledWith(
|
|
38
|
-
"Pass an icon `name` prop or an SVG child to
|
|
38
|
+
"Icon: Pass an icon `name` prop or an SVG child to ensure an icon appears."
|
|
39
39
|
);
|
|
40
40
|
});
|
|
41
41
|
|
|
@@ -82,7 +82,7 @@ export default function Icon(props: React.PropsWithChildren<IconProps>) {
|
|
|
82
82
|
return null;
|
|
83
83
|
} else if (!name && !children) {
|
|
84
84
|
console.warn(
|
|
85
|
-
"Pass an icon `name` prop or an SVG child to
|
|
85
|
+
"Icon: Pass an icon `name` prop or an SVG child to ensure an icon appears."
|
|
86
86
|
);
|
|
87
87
|
return null;
|
|
88
88
|
}
|
|
@@ -22,19 +22,21 @@ export enum IconColors {
|
|
|
22
22
|
UiWhite = "ui.white",
|
|
23
23
|
BrandPrimary = "brand.primary",
|
|
24
24
|
BrandSecondary = "brand.secondary",
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
SectionBlogsPrimary = "section.blogs.primary",
|
|
26
|
+
SectionBlogsSecondary = "section.blogs.secondary",
|
|
27
27
|
SectionBooksAndMorePrimary = "section.books-and-more.primary",
|
|
28
28
|
SectionBooksAndMoreSecondary = "section.books-and-more.secondary",
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
SectionEducationPrimary = "section.education.primary",
|
|
30
|
+
SectionEducationSecondary = "section.education.secondary",
|
|
31
31
|
SectionLocationsPrimary = "section.locations.primary",
|
|
32
32
|
SectionLocationsSecondary = "section.locations.secondary",
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
SectionResearchPrimary = "section.research.primary",
|
|
34
|
+
SectionResearchSecondary = "section.research.secondary",
|
|
35
35
|
SectionResearchLibraryLpa = "section.research-library.lpa",
|
|
36
36
|
SectionResearchLibrarySchomburg = "section.research-library.schomburg",
|
|
37
37
|
SectionResearchLibrarySchwartzman = "section.research-library.schwartzman",
|
|
38
|
+
SectionWhatsOnPrimary = "section.whats-on.primary",
|
|
39
|
+
SectionWhatsOnSecondary = "section.whats-on.secondary",
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
export enum IconSizes {
|
|
@@ -51,7 +51,7 @@ export const enumValues = getStorybookEnumValues(ListTypes, "ListTypes");
|
|
|
51
51
|
| Component Version | DS Version |
|
|
52
52
|
| ----------------- | ---------- |
|
|
53
53
|
| Added | `0.7.0` |
|
|
54
|
-
| Latest | `0.25.
|
|
54
|
+
| Latest | `0.25.12` |
|
|
55
55
|
|
|
56
56
|
<Description of={List} />
|
|
57
57
|
|
|
@@ -63,8 +63,15 @@ export const animalCrossingDefinitions = [
|
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
65
|
term: "Golden trout",
|
|
66
|
-
definition:
|
|
67
|
-
|
|
66
|
+
definition: (
|
|
67
|
+
<p>
|
|
68
|
+
The golden trout is a <b>beautifully</b> colored fish that can only live
|
|
69
|
+
in very clean waters. They are difficult to come across since they are
|
|
70
|
+
found only in high mountain streams. As a side note, I find it much
|
|
71
|
+
easier to appreciate fish that aren't such prima donnas about
|
|
72
|
+
everything.
|
|
73
|
+
</p>
|
|
74
|
+
),
|
|
68
75
|
},
|
|
69
76
|
{
|
|
70
77
|
term: "Rainbowfish",
|
|
@@ -73,8 +80,20 @@ export const animalCrossingDefinitions = [
|
|
|
73
80
|
},
|
|
74
81
|
{
|
|
75
82
|
term: "Suckerfish",
|
|
76
|
-
definition:
|
|
77
|
-
|
|
83
|
+
definition: (
|
|
84
|
+
<p>
|
|
85
|
+
The{" "}
|
|
86
|
+
<Link href="https://animalcrossing.fandom.com/wiki/Suckerfish">
|
|
87
|
+
suckerfish
|
|
88
|
+
</Link>{" "}
|
|
89
|
+
is a curious fish that likes to attach itself with its sucker mouth to
|
|
90
|
+
larger marine animals. The benefit to the suckerfish is that it gets to
|
|
91
|
+
eat smaller parasites and dead skin off the host's body. Amusingly, some
|
|
92
|
+
people have used suckerfish on cords to catch large turtles with the
|
|
93
|
+
fish's own suction! I imagine this practice is the cause of some awkward
|
|
94
|
+
conversations between fish and turtle, eh wot?
|
|
95
|
+
</p>
|
|
96
|
+
),
|
|
78
97
|
},
|
|
79
98
|
];
|
|
80
99
|
export const itemGroups = [
|