@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.
- package/dist/design-system.cjs +9 -5
- package/dist/design-system.js +14 -6
- package/dist/packages/components/Accordion/doc.md +342 -0
- package/dist/packages/components/Badge/doc.md +192 -0
- package/dist/packages/components/Breadcrumbs/doc.md +332 -0
- package/dist/packages/components/Button/doc.md +425 -0
- package/dist/packages/components/Calendar/doc.md +465 -0
- package/dist/packages/components/ChartLegend/doc.md +151 -0
- package/dist/packages/components/ChartTooltip/doc.md +124 -0
- package/dist/packages/components/Checkbox/doc.md +329 -0
- package/dist/packages/components/CheckboxGroup/doc.md +242 -0
- package/dist/packages/components/Chip/doc.md +99 -0
- package/dist/packages/components/Combobox/Combobox.d.ts +8 -0
- package/dist/packages/components/Combobox/doc.md +680 -0
- package/dist/packages/components/DataTable/doc.md +1124 -0
- package/dist/packages/components/DatePicker/doc.md +579 -0
- package/dist/packages/components/DateRangePicker/doc.md +638 -0
- package/dist/packages/components/Drawer/doc.md +338 -0
- package/dist/packages/components/Dropdown/Dropdown.d.ts +4 -0
- package/dist/packages/components/Dropdown/doc.md +205 -0
- package/dist/packages/components/EmptyState/doc.md +101 -0
- package/dist/packages/components/FileUpload/doc.md +449 -0
- package/dist/packages/components/Filter/doc.md +196 -0
- package/dist/packages/components/Header/doc.md +373 -0
- package/dist/packages/components/I18nProvider/doc.md +187 -0
- package/dist/packages/components/Icon/doc.md +63 -0
- package/dist/packages/components/Label/doc.md +60 -0
- package/dist/packages/components/LinearProgressBar/doc.md +148 -0
- package/dist/packages/components/Link/doc.md +206 -0
- package/dist/packages/components/List/doc.md +481 -0
- package/dist/packages/components/Loader/doc.md +53 -0
- package/dist/packages/components/Menu/Menu.d.ts +5 -1
- package/dist/packages/components/Menu/doc.md +231 -0
- package/dist/packages/components/Message/doc.md +166 -0
- package/dist/packages/components/Modal/doc.md +289 -0
- package/dist/packages/components/Navigation/doc.md +992 -0
- package/dist/packages/components/NavigationItem/doc.md +167 -0
- package/dist/packages/components/NotificationCard/doc.md +206 -0
- package/dist/packages/components/Notifications/doc.md +240 -0
- package/dist/packages/components/NumberField/doc.md +582 -0
- package/dist/packages/components/PageLayout/doc.md +651 -0
- package/dist/packages/components/Pagination/doc.md +227 -0
- package/dist/packages/components/Popover/doc.md +245 -0
- package/dist/packages/components/Radio/doc.md +370 -0
- package/dist/packages/components/RouterProvider/doc.md +64 -0
- package/dist/packages/components/SearchBar/doc.md +504 -0
- package/dist/packages/components/SegmentedControl/doc.md +398 -0
- package/dist/packages/components/Select/Select.d.ts +4 -0
- package/dist/packages/components/Select/doc.md +1133 -0
- package/dist/packages/components/Skeleton/doc.md +129 -0
- package/dist/packages/components/Slider/doc.md +362 -0
- package/dist/packages/components/Stepper/doc.md +104 -0
- package/dist/packages/components/Switch/doc.md +296 -0
- package/dist/packages/components/Tabs/doc.md +295 -0
- package/dist/packages/components/Tag/doc.md +81 -0
- package/dist/packages/components/TextInput/doc.md +490 -0
- package/dist/packages/components/TimeField/doc.md +353 -0
- package/dist/packages/components/Timeline/doc.md +1046 -0
- package/dist/packages/components/Toaster/doc.md +263 -0
- package/dist/packages/components/ToggleButton/doc.md +108 -0
- package/dist/packages/components/ToggleButtonGroup/doc.md +307 -0
- package/dist/packages/components/Tooltip/doc.md +206 -0
- package/dist/packages/components/YearMonthPicker/YearMonthPicker.d.ts +8 -0
- package/dist/packages/components/YearMonthPicker/doc.md +638 -0
- package/dist/public_docs/components.md +68 -0
- package/dist/public_docs/index.md +30 -0
- package/dist/public_docs/tokens.md +121 -0
- 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
|
+
```
|