@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,398 @@
1
+ # SegmentedControl
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/SegmentedControl/SegmentedControl.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 SegmentedControl from "./SegmentedControl";
18
+ import SegmentedControlList from "./SegmentedControlList/SegmentedControlList";
19
+ import SegmentedControlButton from "./SegmentedControlButton/SegmentedControlButton";
20
+ import SegmentedControlPanel from "./SegmentedControlPanel/SegmentedControlPanel";
21
+ import { Route, Routes, useLocation } from "react-router-dom";
22
+ import React from "react";
23
+
24
+ const meta: Meta<typeof SegmentedControl> = {
25
+ component: SegmentedControl,
26
+ parameters: {
27
+ layout: "centered",
28
+ },
29
+ };
30
+ export default meta;
31
+
32
+ export const SimpleSegmentedControl: StoryObj<typeof SegmentedControl> = {
33
+ render: () => (
34
+ <SegmentedControl defaultSelectedKey="1">
35
+ <SegmentedControlList style={{ marginBottom: 16 }}>
36
+ <SegmentedControlButton id="1" text="Panel 1" icon="help_outline" />
37
+ <SegmentedControlButton id="2" text="Panel 2" />
38
+ <SegmentedControlButton id="3" text="Panel 3" />
39
+ <SegmentedControlButton id="disabled" isDisabled text="Disabled" />
40
+ </SegmentedControlList>
41
+ <SegmentedControlPanel id="1">
42
+ Content for the panel 1
43
+ </SegmentedControlPanel>
44
+ <SegmentedControlPanel id="2">
45
+ Content for the panel 2
46
+ </SegmentedControlPanel>
47
+ <SegmentedControlPanel id="3">
48
+ Content for the panel 3
49
+ </SegmentedControlPanel>
50
+ <SegmentedControlPanel id="disabled">
51
+ Content for the panel disabled
52
+ </SegmentedControlPanel>
53
+ </SegmentedControl>
54
+ ),
55
+ };
56
+
57
+ export const WithoutFlexWrapper: StoryObj<typeof SegmentedControl> = {
58
+ parameters: {
59
+ layout: "padded",
60
+ },
61
+ render: SimpleSegmentedControl.render,
62
+ };
63
+
64
+ export const ControlledMode: StoryObj<typeof SegmentedControl> = {
65
+ render: () => {
66
+ function Parent() {
67
+ const [selectedKey, setSelectedKey] = React.useState("1");
68
+
69
+ return (
70
+ <SegmentedControl
71
+ selectedKey={selectedKey}
72
+ onSelectionChange={setSelectedKey}
73
+ >
74
+ <SegmentedControlList style={{ marginBottom: 16 }}>
75
+ <SegmentedControlButton id="1" text="Panel 1" />
76
+ <SegmentedControlButton id="2" text="Panel 2" />
77
+ </SegmentedControlList>
78
+ <SegmentedControlPanel id="1">
79
+ Content for the panel 1
80
+ </SegmentedControlPanel>
81
+ <SegmentedControlPanel id="2">
82
+ Content for the panel 2
83
+ </SegmentedControlPanel>
84
+ </SegmentedControl>
85
+ );
86
+ }
87
+
88
+ return <Parent />;
89
+ },
90
+ };
91
+
92
+ export const WithReactRouter: StoryObj<typeof SegmentedControl> = {
93
+ render: () => {
94
+ function Parent() {
95
+ const { pathname } = useLocation();
96
+
97
+ return (
98
+ <SegmentedControl selectedKey={pathname}>
99
+ <SegmentedControlList
100
+ aria-label="SegmentedControl"
101
+ style={{ marginBottom: 16 }}
102
+ >
103
+ <SegmentedControlButton
104
+ id="/pane-1"
105
+ href="/pane-1"
106
+ text="Panel 1"
107
+ />
108
+ <SegmentedControlButton
109
+ id="/pane-2"
110
+ href="/pane-2"
111
+ text="Panel 2"
112
+ />
113
+ <SegmentedControlButton
114
+ id="/pane-3"
115
+ href="/pane-3"
116
+ text="Panel 3"
117
+ />
118
+ <SegmentedControlButton
119
+ id="/pane-disabled"
120
+ href="/pane-disabled"
121
+ isDisabled
122
+ text="Panel disabled"
123
+ />
124
+ </SegmentedControlList>
125
+ <SegmentedControlPanel id={pathname}>
126
+ <Routes>
127
+ <Route path="/pane-1" element="Content for the panel 1" />
128
+ <Route path="/pane-2" element="Content for the panel 2" />
129
+ <Route path="/pane-3" element="Content for the panel 3" />
130
+ <Route
131
+ path="/pane-disabled"
132
+ element="Content for the panel disabled"
133
+ />
134
+ </Routes>
135
+ </SegmentedControlPanel>
136
+ </SegmentedControl>
137
+ );
138
+ }
139
+
140
+ return <Parent />;
141
+ },
142
+ };
143
+ ```
144
+
145
+ ## How to test this component
146
+
147
+ Here are some more advanced stories with more testing coverage and examples that you can read to understand how to test this component.
148
+
149
+ ```tsx
150
+ import { Meta, StoryObj } from "@storybook/react-vite";
151
+ import SegmentedControl from "../SegmentedControl.tsx";
152
+ import {
153
+ SimpleSegmentedControl,
154
+ WithReactRouter,
155
+ } from "../SegmentedControl.stories.tsx";
156
+ import { userEvent, waitFor, within, expect } from "storybook/test";
157
+ import {
158
+ expectNotPresent,
159
+ someTime,
160
+ } from "@internal/test-utils-storybook/test-utils-storybook";
161
+
162
+ const meta: Meta<typeof SegmentedControl> = {
163
+ component: SegmentedControl,
164
+ parameters: {
165
+ layout: "centered",
166
+ chromatic: { disableSnapshot: true },
167
+ },
168
+ };
169
+ export default meta;
170
+
171
+ export const ShouldWorkWithSimpleSegmentedControl: StoryObj<
172
+ typeof SegmentedControl
173
+ > = {
174
+ render: SimpleSegmentedControl.render,
175
+ play: async ({ canvasElement }) => {
176
+ const canvas = within(canvasElement);
177
+ const user = userEvent.setup();
178
+ await canvas.findByText("Panel 1");
179
+ await waitFor(() =>
180
+ expect(canvas.getByText("Panel 1").parentElement).toHaveAttribute(
181
+ "aria-selected",
182
+ "true",
183
+ ),
184
+ );
185
+ await canvas.findByText("Content for the panel 1");
186
+ await user.click(canvas.getByText("Panel 2"));
187
+ await expect(canvas.getByText("Panel 2").parentElement).toHaveAttribute(
188
+ "aria-selected",
189
+ "true",
190
+ );
191
+ await canvas.findByText("Content for the panel 2");
192
+ await user.click(canvas.getByText("Panel 3"));
193
+ await expect(canvas.getByText("Panel 3").parentElement).toHaveAttribute(
194
+ "aria-selected",
195
+ "true",
196
+ );
197
+ await canvas.findByText("Content for the panel 3");
198
+ await user.click(canvas.getByText("Disabled"));
199
+ await expect(canvas.getByText("Disabled").parentElement).toHaveAttribute(
200
+ "aria-selected",
201
+ "false",
202
+ );
203
+ await expectNotPresent(() =>
204
+ canvas.queryByText("Content for the panel disabled"),
205
+ );
206
+ await canvas.findByText("Content for the panel 3");
207
+ },
208
+ };
209
+
210
+ export const ShouldWorkWithReactRouter: StoryObj<typeof SegmentedControl> = {
211
+ render: WithReactRouter.render,
212
+ play: async ({ canvasElement }) => {
213
+ const canvas = within(canvasElement);
214
+ const user = userEvent.setup();
215
+
216
+ await someTime(100); // Avoid flaky tests
217
+
218
+ const checkPanelPresent = async (panelId: string) => {
219
+ await canvas.findByText(`Content for the panel ${panelId}`);
220
+ await expect(
221
+ canvas.getByText(`Panel ${panelId}`).parentElement,
222
+ ).toHaveAttribute("aria-selected", "true");
223
+ };
224
+
225
+ const checkPanelNotPresent = async (panelId: string) => {
226
+ await expectNotPresent(() =>
227
+ canvas.queryByText(`Content for the panel ${panelId}`),
228
+ );
229
+ await expect(
230
+ canvas.getByText(`Panel ${panelId}`).parentElement,
231
+ ).toHaveAttribute("aria-selected", "false");
232
+ };
233
+
234
+ await checkPanelNotPresent("1");
235
+ await checkPanelNotPresent("2");
236
+ await checkPanelNotPresent("3");
237
+ await checkPanelNotPresent("disabled");
238
+
239
+ // Click on the first panel
240
+ await user.click(canvas.getByText("Panel 1"));
241
+ await checkPanelPresent("1");
242
+ await checkPanelNotPresent("2");
243
+ await checkPanelNotPresent("3");
244
+ await checkPanelNotPresent("disabled");
245
+
246
+ // Click on the second panel
247
+ await user.click(canvas.getByText("Panel 2"));
248
+ await checkPanelNotPresent("1");
249
+ await checkPanelPresent("2");
250
+ await checkPanelNotPresent("3");
251
+ await checkPanelNotPresent("disabled");
252
+
253
+ // Click on the third panel
254
+ await user.click(canvas.getByText("Panel 3"));
255
+ await checkPanelNotPresent("1");
256
+ await checkPanelNotPresent("2");
257
+ await checkPanelPresent("3");
258
+ await checkPanelNotPresent("disabled");
259
+
260
+ // Click on the disabled panel
261
+ await user.click(canvas.getByText("Panel disabled"));
262
+ await checkPanelNotPresent("1");
263
+ await checkPanelNotPresent("2");
264
+ await checkPanelPresent("3"); // still present
265
+ await checkPanelNotPresent("disabled");
266
+ },
267
+ };
268
+ ```
269
+
270
+ ## Developer notes
271
+
272
+ 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.
273
+
274
+ ````mdx
275
+ import {
276
+ Canvas,
277
+ Meta,
278
+ Stories,
279
+ ArgTypes,
280
+ Source,
281
+ } from "@storybook/addon-docs/blocks";
282
+
283
+ import * as SegmentedControl from "./SegmentedControl.stories";
284
+ import * as SegmentedControlPanel from "./SegmentedControlPanel/SegmentedControlPanel.stories";
285
+ import * as SegmentedControlList from "./SegmentedControlList/SegmentedControlList.stories";
286
+ import SegmentedControlButton from "./SegmentedControlButton/SegmentedControlButton";
287
+
288
+ <Meta of={SegmentedControl} />
289
+
290
+ # SegmentedControl
291
+
292
+ <Canvas of={SegmentedControl.SimpleSegmentedControl} />
293
+
294
+ ## Basic usage
295
+
296
+ Here is the simplest way to use the SegmentedControl component. All the state is managed by the SegmentedControl component.
297
+ You can define the default selected SegmentedControlButton on the first render with the `defaultSelectedKey` prop.
298
+
299
+ <Source of={SegmentedControl.SimpleSegmentedControl} type="code" dark />
300
+
301
+ ## Controlled mode
302
+
303
+ If you need more control about the state of the SegmentedControl component, you can use the `selectedKey` and `onSelectionChange` props to control the selected SegmentedControlButton.
304
+
305
+ <Source of={SegmentedControl.ControlledMode} type="code" dark />
306
+
307
+ ## Using a Router to render the SegmentedControlPanels
308
+
309
+ It is possible to use a Router to render the SegmentedControlPanels, thus making the SegmentedControl simple links that will update the URL using your framework-specific Router.
310
+
311
+ Doing so may be a little bit more complex than using simple state management, but comes with some benefits like SEO / preserving the browser history / keep the selected panel on page reloads / etc.
312
+
313
+ **It will also requires you to setup the [RouterProvider](?path=/docs/components-routerprovider--docs)** to make the Router available to the SegmentedControl component.
314
+
315
+ Without a RouterProvider, the SegmentedControl will render as simple links that will make a full page reload (instead of a `router.push` or `router.replace` call).
316
+
317
+ Here is a basic example using React Router v6.
318
+
319
+ <Source of={SegmentedControl.WithReactRouter} type="code" dark />
320
+
321
+ If you use `<Outlet />` in your app to render your main routes, you may have to use nested route indications instead of giving a full URL.
322
+
323
+ First, in your main pages routes definitions, you should have a route that will render the same component for the nested paths:
324
+
325
+ ```jsx
326
+ <Route path="/nested/*" element={<NestedPage />} />
327
+ ```
328
+
329
+ Then, inside the NestedPage component, you can use the SegmentedControl component like this :
330
+
331
+ ```tsx
332
+ import { useLocation } from "react-router-dom";
333
+
334
+ export const NestedPage = () => {
335
+ const { pathname } = useLocation();
336
+
337
+ return (
338
+ <>
339
+ <SegmentedControl selectedKey={pathname}>
340
+ <SegmentedControlList>
341
+ <SegmentedControlButton
342
+ id="/nested/pane-1"
343
+ href="/nested/pane-1"
344
+ text="Panel 1"
345
+ />
346
+ <SegmentedControlButton
347
+ id="/nested/pane-2"
348
+ href="/nested/pane-2"
349
+ text="Panel 2"
350
+ />
351
+ <SegmentedControlButton
352
+ id="/nested/pane-3"
353
+ href="/nested/pane-3"
354
+ text="Panel 3"
355
+ />
356
+ </SegmentedControlList>
357
+ <SegmentedControlPanel id={pathname}>
358
+ <Routes>
359
+ {/* 👇 paths are relative to the parent route, no need to give the absolute URL */}
360
+ <Route path="pane-1" element="Content for the panel 1" />
361
+ <Route path="pane-2" element="Content for the panel 2" />
362
+ <Route path="pane-3" element="Content for the panel 3" />
363
+ </Routes>
364
+ </SegmentedControlPanel>
365
+ </SegmentedControl>
366
+ </>
367
+ );
368
+ };
369
+ ```
370
+
371
+ ## SegmentedControl component Props
372
+
373
+ `SegmentedControl` is the root component of the whole SegmentedControl system, other "SegmentedControlButton\*" subcomponents must be above it in the tree.
374
+
375
+ <ArgTypes of={SegmentedControl.SimpleSegmentedControl} />
376
+
377
+ ## SegmentedControlButton component Props
378
+
379
+ The `SegmentedControlButton` component is used to display one of the choices. It can also be a link.
380
+
381
+ <ArgTypes of={SegmentedControlButton} />
382
+
383
+ ## SegmentedControlList component Props
384
+
385
+ The `SegmentedControlList` is responsible to align correctly the different `SegmentedControlButton` component inside of it, and also enable a11y features like keyboard navigation and screen-reader props.
386
+
387
+ <ArgTypes of={SegmentedControlList.Default} />
388
+
389
+ ## SegmentedControlPanel component Props
390
+
391
+ This optional component is required if you want the `SegmentedControl` to fully handle the state (uncontrolled) and show the corresponding active panel depending on the selected SegmentedControlButton ID.
392
+
393
+ If you use the controlled mode, it's still good to use SegmentedControlPanel but it's not required.
394
+
395
+ <ArgTypes of={SegmentedControlPanel.Default} />
396
+
397
+ <Stories />
398
+ ````
@@ -60,6 +60,10 @@ interface GenericProps extends Pick<LabelProps, "label" | "labelIconRight" | "la
60
60
  * If you give a ReactNode as label, you should then provide an aria-label as string to ensure there is no accessibility issue
61
61
  */
62
62
  "aria-label"?: string;
63
+ /**
64
+ * When true, increases the dropdown max-height from 200px to 400px.
65
+ */
66
+ tallDropdown?: boolean;
63
67
  }
64
68
  interface SelectSingleProps extends GenericProps {
65
69
  /**