@agregio-solutions/design-system 1.90.1 → 1.92.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.
Files changed (68) hide show
  1. package/dist/design-system.cjs +9 -5
  2. package/dist/design-system.js +14 -6
  3. package/dist/packages/components/Accordion/doc.md +342 -0
  4. package/dist/packages/components/Badge/doc.md +192 -0
  5. package/dist/packages/components/Breadcrumbs/doc.md +332 -0
  6. package/dist/packages/components/Button/doc.md +425 -0
  7. package/dist/packages/components/Calendar/doc.md +465 -0
  8. package/dist/packages/components/ChartLegend/doc.md +151 -0
  9. package/dist/packages/components/ChartTooltip/doc.md +124 -0
  10. package/dist/packages/components/Checkbox/doc.md +329 -0
  11. package/dist/packages/components/CheckboxGroup/doc.md +242 -0
  12. package/dist/packages/components/Chip/doc.md +99 -0
  13. package/dist/packages/components/Combobox/Combobox.d.ts +8 -0
  14. package/dist/packages/components/Combobox/doc.md +680 -0
  15. package/dist/packages/components/DataTable/doc.md +1124 -0
  16. package/dist/packages/components/DatePicker/doc.md +579 -0
  17. package/dist/packages/components/DateRangePicker/doc.md +638 -0
  18. package/dist/packages/components/Drawer/doc.md +338 -0
  19. package/dist/packages/components/Dropdown/Dropdown.d.ts +4 -0
  20. package/dist/packages/components/Dropdown/doc.md +205 -0
  21. package/dist/packages/components/EmptyState/doc.md +101 -0
  22. package/dist/packages/components/FileUpload/doc.md +449 -0
  23. package/dist/packages/components/Filter/doc.md +196 -0
  24. package/dist/packages/components/Header/doc.md +373 -0
  25. package/dist/packages/components/I18nProvider/doc.md +187 -0
  26. package/dist/packages/components/Icon/doc.md +63 -0
  27. package/dist/packages/components/Label/doc.md +60 -0
  28. package/dist/packages/components/LinearProgressBar/doc.md +148 -0
  29. package/dist/packages/components/Link/doc.md +206 -0
  30. package/dist/packages/components/List/doc.md +481 -0
  31. package/dist/packages/components/Loader/doc.md +53 -0
  32. package/dist/packages/components/Menu/Menu.d.ts +5 -1
  33. package/dist/packages/components/Menu/doc.md +231 -0
  34. package/dist/packages/components/Message/doc.md +166 -0
  35. package/dist/packages/components/Modal/doc.md +289 -0
  36. package/dist/packages/components/Navigation/doc.md +992 -0
  37. package/dist/packages/components/NavigationItem/doc.md +167 -0
  38. package/dist/packages/components/NotificationCard/doc.md +206 -0
  39. package/dist/packages/components/Notifications/doc.md +240 -0
  40. package/dist/packages/components/NumberField/doc.md +582 -0
  41. package/dist/packages/components/PageLayout/doc.md +651 -0
  42. package/dist/packages/components/Pagination/doc.md +227 -0
  43. package/dist/packages/components/Popover/doc.md +245 -0
  44. package/dist/packages/components/Radio/doc.md +370 -0
  45. package/dist/packages/components/RouterProvider/doc.md +64 -0
  46. package/dist/packages/components/SearchBar/doc.md +504 -0
  47. package/dist/packages/components/SegmentedControl/doc.md +398 -0
  48. package/dist/packages/components/Select/Select.d.ts +4 -0
  49. package/dist/packages/components/Select/doc.md +1133 -0
  50. package/dist/packages/components/Skeleton/doc.md +129 -0
  51. package/dist/packages/components/Slider/doc.md +362 -0
  52. package/dist/packages/components/Stepper/doc.md +104 -0
  53. package/dist/packages/components/Switch/doc.md +296 -0
  54. package/dist/packages/components/Tabs/doc.md +295 -0
  55. package/dist/packages/components/Tag/doc.md +81 -0
  56. package/dist/packages/components/TextInput/doc.md +490 -0
  57. package/dist/packages/components/TimeField/doc.md +353 -0
  58. package/dist/packages/components/Timeline/doc.md +1046 -0
  59. package/dist/packages/components/Toaster/doc.md +263 -0
  60. package/dist/packages/components/ToggleButton/doc.md +108 -0
  61. package/dist/packages/components/ToggleButtonGroup/doc.md +307 -0
  62. package/dist/packages/components/Tooltip/doc.md +206 -0
  63. package/dist/packages/components/YearMonthPicker/YearMonthPicker.d.ts +8 -0
  64. package/dist/packages/components/YearMonthPicker/doc.md +638 -0
  65. package/dist/public_docs/components.md +68 -0
  66. package/dist/public_docs/index.md +30 -0
  67. package/dist/public_docs/tokens.md +121 -0
  68. package/package.json +3 -2
@@ -0,0 +1,124 @@
1
+ # ChartTooltip
2
+
3
+ ## Props
4
+
5
+ The complete Props documentation with JS doc for this component is available at this path:
6
+
7
+ node_modules/@agregio-solutions/design-system/dist/packages/components/ChartTooltip/ChartTooltip.d.ts
8
+
9
+ ## Example usage
10
+
11
+ Here are the Storybook Stories.
12
+
13
+ Base stories:
14
+
15
+ ```tsx
16
+ import { Meta, StoryObj } from "@storybook/react-vite";
17
+ import { expect, within } from "storybook/test";
18
+ import ChartTooltip from "./ChartTooltip";
19
+
20
+ const meta: Meta<typeof ChartTooltip> = {
21
+ component: ChartTooltip,
22
+ tags: ["autodocs"],
23
+ parameters: {
24
+ layout: "centered",
25
+ },
26
+ argTypes: {
27
+ footerSlot: { control: "text" },
28
+ },
29
+ };
30
+ export default meta;
31
+
32
+ type Story = StoryObj<typeof meta>;
33
+
34
+ export const Playground: Story = {
35
+ args: {
36
+ title: "Title 1",
37
+ items: [
38
+ { text: "Item : Value #", color: "#4A90E2" },
39
+ { text: "Item : Value #", color: "#7ED321", icon: "plainline" },
40
+ { text: "Item : Value #", color: "#50E3C2", icon: "dottedline" },
41
+ ],
42
+ description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
43
+ bodyTitle: "Zone 2 title",
44
+ bodyContent: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
45
+ footerSlot: (
46
+ <div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
47
+ <span>↔</span>
48
+ <span>Slot component</span>
49
+ </div>
50
+ ),
51
+ style: {
52
+ maxWidth: "240px",
53
+ },
54
+ },
55
+ play: async ({ canvasElement }) => {
56
+ const canvas = within(canvasElement);
57
+ await canvas.findByText("Title 1");
58
+ await canvas.findByText("Zone 2 title");
59
+ await expect(await canvas.findAllByText("Item : Value #")).toHaveLength(3);
60
+ await expect(await canvas.findAllByText(/Lorem ipsum/)).toHaveLength(2);
61
+ await canvas.findByText("Slot component");
62
+ },
63
+ };
64
+
65
+ export const WithHeaderOnly: Story = {
66
+ args: {
67
+ title: "Simple Tooltip",
68
+ items: [
69
+ { text: "Metric A : 100%", color: "#FF6B6B" },
70
+ { text: "Metric B : 75%", color: "#4ECDC4" },
71
+ ],
72
+ },
73
+ };
74
+
75
+ export const WithBody: Story = {
76
+ args: {
77
+ title: "Tooltip with Body",
78
+ items: [{ text: "Data : 42", color: "#45B7D1" }],
79
+ bodyTitle: "Additional Information",
80
+ bodyContent: "This is additional context for the tooltip content.",
81
+ },
82
+ };
83
+
84
+ export const WithFooter: Story = {
85
+ args: {
86
+ title: "Tooltip with Footer",
87
+ items: [{ text: "Status : Active", color: "#96CEB4" }],
88
+ footerSlot: <div>Read-only information</div>,
89
+ },
90
+ };
91
+
92
+ export const EmptyItems: Story = {
93
+ args: {
94
+ title: "Tooltip without items",
95
+ description: "This tooltip shows only the title and body content.",
96
+ items: [],
97
+ },
98
+ };
99
+
100
+ export const OnlyOneItem: Story = {
101
+ args: {
102
+ title: "SPOT : -3,50 €",
103
+ description: "24/09/25 - 13:00",
104
+ },
105
+ };
106
+
107
+ export const WithOutlineColor: Story = {
108
+ args: {
109
+ title: "Tooltip with Outline Color",
110
+ items: [
111
+ {
112
+ text: "Data : 42",
113
+ color: "var(--color-content-dataviz-azure-1)",
114
+ outlineColor: "var(--color-content-dataviz-azure-3)",
115
+ },
116
+ {
117
+ text: "Data : 50",
118
+ color: "var(--color-content-dataviz-orange-1)",
119
+ outlineColor: "var(--color-content-dataviz-orange-3)",
120
+ },
121
+ ],
122
+ },
123
+ };
124
+ ```
@@ -0,0 +1,329 @@
1
+ # Checkbox
2
+
3
+ ## Props
4
+
5
+ The complete Props documentation with JS doc for this component is available at this path:
6
+
7
+ node_modules/@agregio-solutions/design-system/dist/packages/components/Checkbox/Checkbox.d.ts
8
+
9
+ ## Example usage
10
+
11
+ Here are the Storybook Stories.
12
+
13
+ Base stories:
14
+
15
+ ```tsx
16
+ import { Meta, StoryObj } from "@storybook/react-vite";
17
+ import Checkbox from "./Checkbox";
18
+ import { expect, fireEvent, fn, within } from "storybook/test";
19
+
20
+ const meta: Meta<typeof Checkbox> = {
21
+ component: Checkbox,
22
+ argTypes: {
23
+ defaultSelected: { control: false },
24
+ },
25
+ parameters: {
26
+ layout: "centered",
27
+ },
28
+ };
29
+ export default meta;
30
+
31
+ // Be warned ! There is a known issue with the userEvent.click on checkbox inputs in Firefox
32
+ // This is why we use a mix of userEvent and fireEvent, waiting for a fix in userEvent
33
+ // See: https://github.com/testing-library/user-event/issues/1149
34
+
35
+ export const Playground: StoryObj<typeof Checkbox> = {
36
+ args: {
37
+ label: "Label",
38
+ onChange: fn(),
39
+ },
40
+ };
41
+
42
+ export const WithLabel: StoryObj<typeof Checkbox> = {
43
+ args: {
44
+ ...Playground.args,
45
+ },
46
+ play: async ({ canvasElement }) => {
47
+ const canvas = within(canvasElement);
48
+ await canvas.findByText("Label");
49
+ await expect(canvas.getByLabelText("Label")).not.toBeChecked();
50
+ },
51
+ };
52
+
53
+ export const WithLabelDefaultSelected: StoryObj<typeof Checkbox> = {
54
+ args: {
55
+ ...Playground.args,
56
+ defaultSelected: true,
57
+ },
58
+ play: async ({ canvasElement }) => {
59
+ const canvas = within(canvasElement);
60
+ await canvas.findByText("Label");
61
+ await expect(canvas.getByLabelText("Label")).toBeChecked();
62
+ },
63
+ };
64
+
65
+ export const WithLabelDisabled: StoryObj<typeof Checkbox> = {
66
+ args: {
67
+ ...Playground.args,
68
+ disabled: true,
69
+ },
70
+ play: async ({ canvasElement }) => {
71
+ const canvas = within(canvasElement);
72
+ await canvas.findByText("Label");
73
+ await expect(canvas.getByLabelText("Label")).not.toBeChecked();
74
+ await expect(canvas.getByLabelText("Label")).toBeDisabled();
75
+ await fireEvent.click(canvas.getByLabelText("Label"));
76
+ await expect(canvas.getByLabelText("Label")).not.toBeChecked();
77
+ },
78
+ };
79
+
80
+ export const WithLabelIndeterminate: StoryObj<typeof Checkbox> = {
81
+ args: {
82
+ ...Playground.args,
83
+ isIndeterminate: true,
84
+ },
85
+ play: async ({ canvasElement }) => {
86
+ const canvas = within(canvasElement);
87
+ await canvas.findByText("Label");
88
+ await expect(canvas.getByLabelText("Label")).not.toBeChecked();
89
+ },
90
+ };
91
+
92
+ export const WithLabelReadOnly: StoryObj<typeof Checkbox> = {
93
+ args: {
94
+ ...Playground.args,
95
+ readOnly: true,
96
+ },
97
+ play: async ({ canvasElement }) => {
98
+ const canvas = within(canvasElement);
99
+ await canvas.findByText("Label");
100
+ await expect(canvas.getByLabelText("Label")).not.toBeChecked();
101
+ await fireEvent.click(canvas.getByLabelText("Label"));
102
+ await expect(canvas.getByLabelText("Label")).not.toBeChecked();
103
+ },
104
+ };
105
+
106
+ export const WithLabelFocus: StoryObj<typeof Checkbox> = {
107
+ args: {
108
+ ...Playground.args,
109
+ // @ts-ignore
110
+ "data-force-focus": true,
111
+ },
112
+ };
113
+
114
+ export const WithoutLabel: StoryObj<typeof Checkbox> = {
115
+ args: {
116
+ ...Playground.args,
117
+ hideLabel: true,
118
+ },
119
+ play: async ({ canvasElement }) => {
120
+ const canvas = within(canvasElement);
121
+ await expect(canvas.getByLabelText("Label")).not.toBeChecked();
122
+ },
123
+ };
124
+
125
+ export const WithoutLabelDefaultSelected: StoryObj<typeof Checkbox> = {
126
+ args: {
127
+ ...WithoutLabel.args,
128
+ defaultSelected: true,
129
+ },
130
+ play: async ({ canvasElement }) => {
131
+ const canvas = within(canvasElement);
132
+ await expect(canvas.getByLabelText("Label")).toBeChecked();
133
+ },
134
+ };
135
+
136
+ export const WithoutLabelDisabled: StoryObj<typeof Checkbox> = {
137
+ args: {
138
+ ...WithoutLabel.args,
139
+ disabled: true,
140
+ },
141
+ play: async ({ canvasElement }) => {
142
+ const canvas = within(canvasElement);
143
+ await expect(canvas.getByLabelText("Label")).not.toBeChecked();
144
+ await expect(canvas.getByLabelText("Label")).toBeDisabled();
145
+ await fireEvent.click(canvas.getByLabelText("Label"));
146
+ await expect(canvas.getByLabelText("Label")).not.toBeChecked();
147
+ },
148
+ };
149
+
150
+ export const WithoutLabelIndeterminate: StoryObj<typeof Checkbox> = {
151
+ args: {
152
+ ...WithoutLabel.args,
153
+ isIndeterminate: true,
154
+ },
155
+ play: async ({ canvasElement }) => {
156
+ const canvas = within(canvasElement);
157
+ await expect(canvas.getByLabelText("Label")).not.toBeChecked();
158
+ },
159
+ };
160
+
161
+ export const WithoutLabelReadOnly: StoryObj<typeof Checkbox> = {
162
+ args: {
163
+ ...WithoutLabel.args,
164
+ readOnly: true,
165
+ },
166
+ play: async ({ canvasElement }) => {
167
+ const canvas = within(canvasElement);
168
+ await expect(canvas.getByLabelText("Label")).not.toBeChecked();
169
+ await fireEvent.click(canvas.getByLabelText("Label"));
170
+ await expect(canvas.getByLabelText("Label")).not.toBeChecked();
171
+ },
172
+ };
173
+
174
+ export const WithoutLabelFocus: StoryObj<typeof Checkbox> = {
175
+ args: {
176
+ ...WithoutLabel.args,
177
+ // @ts-ignore
178
+ "data-force-focus": true,
179
+ },
180
+ };
181
+ ```
182
+
183
+ ## How to test this component
184
+
185
+ Here are some more advanced stories with more testing coverage and examples that you can read to understand how to test this component.
186
+
187
+ ```tsx
188
+ import { Meta, StoryObj } from "@storybook/react-vite";
189
+ import Checkbox from "../Checkbox";
190
+ import React from "react";
191
+ import { expect, fireEvent, within } from "storybook/test";
192
+ import { useController, useForm } from "react-hook-form";
193
+ import { someTime } from "@internal/test-utils-storybook/test-utils-storybook";
194
+
195
+ const meta: Meta<typeof Checkbox> = {
196
+ component: Checkbox,
197
+ parameters: {
198
+ layout: "centered",
199
+ chromatic: { disableSnapshot: true },
200
+ },
201
+ };
202
+ export default meta;
203
+
204
+ // Be warned ! There is a known issue with the userEvent.click on checkbox inputs in Firefox
205
+ // This is why we use a mix of userEvent and fireEvent, waiting for a fix in userEvent
206
+ // See: https://github.com/testing-library/user-event/issues/1149
207
+
208
+ export const ExampleControlled: StoryObj<typeof Checkbox> = {
209
+ render: () => {
210
+ function Example() {
211
+ const [selected, setSelection] = React.useState(false);
212
+
213
+ return (
214
+ <>
215
+ <Checkbox
216
+ label="Label"
217
+ isSelected={selected}
218
+ onChange={setSelection}
219
+ />
220
+
221
+ <p>{`The checkbox is ${selected ? "selected" : "unselected"}`}</p>
222
+ </>
223
+ );
224
+ }
225
+
226
+ return <Example />;
227
+ },
228
+ };
229
+
230
+ export const TestControlled: StoryObj<typeof Checkbox> = {
231
+ render: ExampleControlled.render,
232
+ play: async ({ canvasElement }) => {
233
+ const canvas = within(canvasElement);
234
+ await canvas.findByText("The checkbox is unselected");
235
+ await expect(canvas.getByLabelText("Label")).not.toBeChecked();
236
+ await fireEvent.click(canvas.getByLabelText("Label"));
237
+ await canvas.findByText("The checkbox is selected");
238
+ await expect(canvas.getByLabelText("Label")).toBeChecked();
239
+ },
240
+ };
241
+
242
+ export const ExampleWithReactHookForm: StoryObj<typeof Checkbox> = {
243
+ render: (args) => {
244
+ const ReactHookFormExample = () => {
245
+ const { control } = useForm<any>();
246
+ const checkBoxField = useController({
247
+ control,
248
+ name: "checkbox",
249
+ });
250
+
251
+ return (
252
+ <>
253
+ <Checkbox
254
+ label="Label"
255
+ isSelected={checkBoxField.field.value}
256
+ onChange={(selected) => checkBoxField.field.onChange(selected)}
257
+ />
258
+
259
+ <p>{`The checkbox is ${checkBoxField.field.value ? "selected" : "unselected"}`}</p>
260
+ </>
261
+ );
262
+ };
263
+
264
+ return <ReactHookFormExample {...args} />;
265
+ },
266
+ };
267
+
268
+ export const TestWithReactHookForm: StoryObj<typeof Checkbox> = {
269
+ render: ExampleWithReactHookForm.render,
270
+ play: async ({ canvasElement }) => {
271
+ const canvas = within(canvasElement);
272
+ await someTime(250);
273
+ await canvas.findByText("The checkbox is unselected");
274
+ await expect(canvas.getByLabelText("Label")).not.toBeChecked();
275
+ await fireEvent.click(canvas.getByLabelText("Label"));
276
+ await canvas.findByText("The checkbox is selected");
277
+ await expect(canvas.getByLabelText("Label")).toBeChecked();
278
+ },
279
+ };
280
+ ```
281
+
282
+ ## Developer notes
283
+
284
+ Here are the notes available for the developer on the built Storybook, you can read them to understand the component and how to use it.
285
+
286
+ ```mdx
287
+ import {
288
+ Canvas,
289
+ Controls,
290
+ Meta,
291
+ Source,
292
+ Stories,
293
+ } from "@storybook/addon-docs/blocks";
294
+
295
+ import * as Checkbox from "./Checkbox.stories";
296
+ import * as CheckboxTests from "./tests/Checkbox.stories";
297
+
298
+ <Meta of={Checkbox} />
299
+
300
+ # Checkbox
301
+
302
+ <Canvas of={Checkbox.Playground} />
303
+
304
+ ## Checkbox props
305
+
306
+ <Controls of={Checkbox.Playground} />
307
+
308
+ ## Code examples
309
+
310
+ ### Basic usage
311
+
312
+ This is how you generally want to use the `Checkbox` component.
313
+ You can control the value of the checkbox by passing the `isSelected` and `onChange` props.
314
+
315
+ <Source of={CheckboxTests.ExampleControlled} type="code" dark />
316
+
317
+ ### React Hook Form
318
+
319
+ Here is another example of how to use the `Checkbox` component with `react-hook-form`.
320
+ Since the Checkbox component manages its state internally, you have to use `useController` (or the Controller component) from React Hook Form to integrate with it in a controlled mode.
321
+
322
+ More information about this technical limitation on the [react-hook-form docs](https://www.react-hook-form.com/get-started/#IntegratingwithUIlibraries) and also in [React Aria docs](https://react-spectrum.adobe.com/react-aria/forms.html#react-hook-form)
323
+
324
+ <Source of={CheckboxTests.ExampleWithReactHookForm} type="code" dark />
325
+
326
+ ## Stories
327
+
328
+ <Stories of={Checkbox} />
329
+ ```
@@ -0,0 +1,242 @@
1
+ # CheckboxGroup
2
+
3
+ ## Props
4
+
5
+ The complete Props documentation with JS doc for this component is available at this path:
6
+
7
+ node_modules/@agregio-solutions/design-system/dist/packages/components/CheckboxGroup/CheckboxGroup.d.ts
8
+
9
+ ## Example usage
10
+
11
+ Here are the Storybook Stories.
12
+
13
+ Base stories:
14
+
15
+ ```tsx
16
+ import { Meta, StoryObj } from "@storybook/react-vite";
17
+ import CheckboxGroup from "./CheckboxGroup";
18
+ import { userEvent, within, waitFor, expect, fn } from "storybook/test";
19
+ import Checkbox from "@components/Checkbox/Checkbox";
20
+
21
+ const meta: Meta<typeof CheckboxGroup> = {
22
+ component: CheckboxGroup,
23
+ argTypes: {
24
+ children: { control: false },
25
+ className: { control: "text" },
26
+ value: { control: false },
27
+ },
28
+ parameters: {
29
+ layout: "centered",
30
+ },
31
+ };
32
+ export default meta;
33
+
34
+ export const Playground: StoryObj<typeof CheckboxGroup> = {
35
+ args: {
36
+ "aria-label": "Checkbox Group",
37
+ children: (
38
+ <>
39
+ <Checkbox label="Option 1" value="1" />
40
+ <Checkbox label="Option 2" value="2" />
41
+ <Checkbox label="Option 3" value="3" />
42
+ </>
43
+ ),
44
+ isDisabled: false,
45
+ isReadOnly: false,
46
+ onChange: fn(),
47
+ className: "",
48
+ style: {
49
+ display: "flex",
50
+ flexDirection: "column",
51
+ alignItems: "flex-start",
52
+ },
53
+ },
54
+ };
55
+
56
+ export const Disabled: StoryObj<typeof CheckboxGroup> = {
57
+ args: {
58
+ ...Playground.args,
59
+ isDisabled: true,
60
+ },
61
+ play: async ({ canvasElement, args }) => {
62
+ const canvas = within(canvasElement);
63
+ const user = userEvent.setup({ delay: 50 });
64
+ await expect(canvas.getByLabelText("Option 1")).toBeDisabled();
65
+ await user.click(canvas.getByText("Option 1"));
66
+ await expect(canvas.getByLabelText("Option 2")).toBeDisabled();
67
+ await user.click(canvas.getByText("Option 2"));
68
+ await expect(canvas.getByLabelText("Option 3")).toBeDisabled();
69
+ await user.click(canvas.getByText("Option 3"));
70
+ await waitFor(() => expect(args.onChange).not.toHaveBeenCalled());
71
+ },
72
+ };
73
+
74
+ export const ReadOnly: StoryObj<typeof CheckboxGroup> = {
75
+ args: {
76
+ ...Playground.args,
77
+ isReadOnly: true,
78
+ },
79
+ play: async ({ canvasElement, args }) => {
80
+ const canvas = within(canvasElement);
81
+ const user = userEvent.setup({ delay: 50 });
82
+ await user.click(canvas.getByText("Option 1"));
83
+ await user.click(canvas.getByText("Option 2"));
84
+ await user.click(canvas.getByText("Option 3"));
85
+ await waitFor(() => expect(args.onChange).not.toHaveBeenCalled());
86
+ },
87
+ };
88
+ ```
89
+
90
+ ## How to test this component
91
+
92
+ Here are some more advanced stories with more testing coverage and examples that you can read to understand how to test this component.
93
+
94
+ ```tsx
95
+ import { Meta, StoryObj } from "@storybook/react-vite";
96
+ import CheckboxGroup from "../CheckboxGroup";
97
+ import { userEvent, within, waitFor, expect } from "storybook/test";
98
+ import { Playground } from "../CheckboxGroup.stories";
99
+ import { useState } from "react";
100
+ import Checkbox from "@components/Checkbox/Checkbox";
101
+ import Radio from "@components/Radio/Radio";
102
+ import { useController, useForm } from "react-hook-form";
103
+
104
+ const meta: Meta<typeof CheckboxGroup> = {
105
+ component: CheckboxGroup,
106
+ parameters: {
107
+ layout: "centered",
108
+ chromatic: { disableSnapshot: true },
109
+ },
110
+ };
111
+ export default meta;
112
+
113
+ export const TestShouldSelectTheItems: StoryObj<typeof CheckboxGroup> = {
114
+ args: {
115
+ ...Playground.args,
116
+ },
117
+ play: async ({ canvasElement, args }) => {
118
+ const canvas = within(canvasElement);
119
+ const user = userEvent.setup({ delay: 50 });
120
+ await user.click(canvas.getByText("Option 1"));
121
+ await waitFor(() => expect(args.onChange).toHaveBeenCalledTimes(1));
122
+ await waitFor(() => expect(args.onChange).toHaveBeenCalledWith(["1"]));
123
+ await user.click(canvas.getByText("Option 2"));
124
+ await waitFor(() => expect(args.onChange).toHaveBeenCalledTimes(2));
125
+ await waitFor(() => expect(args.onChange).toHaveBeenCalledWith(["1", "2"]));
126
+ await user.click(canvas.getByText("Option 3"));
127
+ await waitFor(() => expect(args.onChange).toHaveBeenCalledTimes(3));
128
+ await waitFor(() =>
129
+ expect(args.onChange).toHaveBeenCalledWith(["1", "2", "3"]),
130
+ );
131
+ await user.click(canvas.getByText("Option 2"));
132
+ await waitFor(() => expect(args.onChange).toHaveBeenCalledTimes(4));
133
+ await waitFor(() => expect(args.onChange).toHaveBeenCalledWith(["1", "3"]));
134
+ },
135
+ };
136
+
137
+ export const ExampleControlled: StoryObj<typeof CheckboxGroup> = {
138
+ render: () => {
139
+ const ParentComponent = () => {
140
+ const [value, setValue] = useState<Array<string>>([]);
141
+
142
+ return (
143
+ <div>
144
+ Selected values: {value.join(", ")}
145
+ <CheckboxGroup
146
+ value={value}
147
+ onChange={setValue}
148
+ aria-label="Checkbox Group"
149
+ >
150
+ <Checkbox label="Option 1" value="1" />
151
+ <Checkbox label="Option 2" value="2" />
152
+ <Checkbox label="Option 3" value="3" />
153
+ </CheckboxGroup>
154
+ </div>
155
+ );
156
+ };
157
+
158
+ return <ParentComponent />;
159
+ },
160
+ };
161
+
162
+ export const ExampleWithReactHookForm: StoryObj<typeof Radio> = {
163
+ render: (args) => {
164
+ const ReactHookFormExample = () => {
165
+ const { control } = useForm({
166
+ defaultValues: {
167
+ checkboxes: [],
168
+ },
169
+ });
170
+
171
+ const checkboxesField = useController({ name: "checkboxes", control });
172
+
173
+ return (
174
+ <form>
175
+ <div>Selected values: {checkboxesField.field.value.join(", ")}</div>
176
+ <div>
177
+ <CheckboxGroup
178
+ value={checkboxesField.field.value}
179
+ onChange={checkboxesField.field.onChange}
180
+ aria-label="Checkbox Group"
181
+ >
182
+ <Checkbox label="Option 1" value="1" />
183
+ <Checkbox label="Option 2" value="2" />
184
+ <Checkbox label="Option 3" value="3" />
185
+ </CheckboxGroup>
186
+ </div>
187
+ </form>
188
+ );
189
+ };
190
+
191
+ return <ReactHookFormExample {...args} />;
192
+ },
193
+ };
194
+ ```
195
+
196
+ ## Developer notes
197
+
198
+ Here are the notes available for the developer on the built Storybook, you can read them to understand the component and how to use it.
199
+
200
+ ```mdx
201
+ import {
202
+ Meta,
203
+ Canvas,
204
+ Controls,
205
+ Source,
206
+ Stories,
207
+ } from "@storybook/addon-docs/blocks";
208
+
209
+ import * as CheckboxGroup from "./CheckboxGroup.stories";
210
+ import * as CheckboxGroupTests from "./tests/CheckboxGroup.stories";
211
+
212
+ <Meta of={CheckboxGroup} />
213
+
214
+ # CheckboxGroup
215
+
216
+ This component is a helper to manage a group of checkboxes.
217
+
218
+ <Canvas of={CheckboxGroup.Playground} />
219
+
220
+ ## CheckboxGroup props
221
+
222
+ <Controls of={CheckboxGroup.Playground} />
223
+
224
+ ## Code examples
225
+
226
+ ### Basic usage
227
+
228
+ <Source of={CheckboxGroupTests.ExampleControlled} type="code" dark />
229
+
230
+ ### React Hook Form
231
+
232
+ Here is another example of how to use the `CheckboxGroup` component with `react-hook-form`.
233
+ Since the Checkbox component manages its state internally, you have to use `useController` (or the Controller component) from React Hook Form to integrate with it in a controlled mode.
234
+
235
+ More information about this technical limitation on the [react-hook-form docs](https://www.react-hook-form.com/get-started/#IntegratingwithUIlibraries) and also in [React Aria docs](https://react-spectrum.adobe.com/react-aria/forms.html#react-hook-form)
236
+
237
+ <Source of={CheckboxGroupTests.ExampleWithReactHookForm} type="code" dark />
238
+
239
+ ## Stories
240
+
241
+ <Stories of={CheckboxGroup} />
242
+ ```