@agregio-solutions/design-system 1.95.0 → 1.96.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 +224 -218
- package/dist/design-system.js +5995 -6001
- package/dist/packages/components/Card/doc.md +202 -0
- package/dist/packages/components/Combobox/doc.md +25 -0
- package/dist/packages/components/DataTable/DataTableHeader/DataTableHeader.d.ts +4 -1
- package/dist/packages/components/DatePicker/doc.md +1 -1
- package/dist/packages/components/DateRangePicker/doc.md +1 -1
- package/dist/packages/components/SelectItem/SelectItem.d.ts +7 -1
- package/dist/packages/components/TimeField/TimeField.d.ts +12 -10
- package/dist/packages/components/TimeField/doc.md +115 -15
- package/dist/public_docs/components.md +1 -0
- package/package.json +1 -3
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# Card
|
|
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/Card/Card.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 { within, expect } from "storybook/test";
|
|
18
|
+
import Card from "./Card";
|
|
19
|
+
import Button from "../Button/Button";
|
|
20
|
+
import Icon from "../Icon/Icon";
|
|
21
|
+
|
|
22
|
+
const meta: Meta<typeof Card> = {
|
|
23
|
+
component: Card,
|
|
24
|
+
tags: ["autodocs"],
|
|
25
|
+
argTypes: {
|
|
26
|
+
children: { control: false },
|
|
27
|
+
},
|
|
28
|
+
parameters: {
|
|
29
|
+
layout: "centered",
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
export default meta;
|
|
33
|
+
|
|
34
|
+
type Story = StoryObj<typeof meta>;
|
|
35
|
+
|
|
36
|
+
const defaultArgs: Story["args"] = {
|
|
37
|
+
children: <div>Card content</div>,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const getCard = (canvasElement: HTMLElement) =>
|
|
41
|
+
within(canvasElement)
|
|
42
|
+
.getByText("Card content")
|
|
43
|
+
.closest('[data-design-system-component="Card"]');
|
|
44
|
+
|
|
45
|
+
export const Playground: Story = {
|
|
46
|
+
args: defaultArgs,
|
|
47
|
+
play: async ({ canvasElement }) => {
|
|
48
|
+
const canvas = within(canvasElement);
|
|
49
|
+
await canvas.findByText("Card content");
|
|
50
|
+
await expect(getCard(canvasElement)).toHaveAttribute("data-size", "md");
|
|
51
|
+
await expect(getCard(canvasElement)).toHaveAttribute("data-radius", "full");
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const NoPadding: Story = {
|
|
56
|
+
args: { ...defaultArgs, size: "no-padding" },
|
|
57
|
+
play: async ({ canvasElement }) => {
|
|
58
|
+
await within(canvasElement).findByText("Card content");
|
|
59
|
+
await expect(getCard(canvasElement)).not.toHaveAttribute("data-size");
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const PaddingSm: Story = {
|
|
64
|
+
args: { ...defaultArgs, size: "sm" },
|
|
65
|
+
play: async ({ canvasElement }) => {
|
|
66
|
+
await within(canvasElement).findByText("Card content");
|
|
67
|
+
await expect(getCard(canvasElement)).toHaveAttribute("data-size", "sm");
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const PaddingLg: Story = {
|
|
72
|
+
args: { ...defaultArgs, size: "lg" },
|
|
73
|
+
play: async ({ canvasElement }) => {
|
|
74
|
+
await within(canvasElement).findByText("Card content");
|
|
75
|
+
await expect(getCard(canvasElement)).toHaveAttribute("data-size", "lg");
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const RadiusMinimal: Story = {
|
|
80
|
+
args: { ...defaultArgs, radius: "minimal" },
|
|
81
|
+
play: async ({ canvasElement }) => {
|
|
82
|
+
await within(canvasElement).findByText("Card content");
|
|
83
|
+
await expect(getCard(canvasElement)).toHaveAttribute(
|
|
84
|
+
"data-radius",
|
|
85
|
+
"minimal",
|
|
86
|
+
);
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const RadiusRounded: Story = {
|
|
91
|
+
args: { ...defaultArgs, radius: "rounded" },
|
|
92
|
+
play: async ({ canvasElement }) => {
|
|
93
|
+
await within(canvasElement).findByText("Card content");
|
|
94
|
+
await expect(getCard(canvasElement)).toHaveAttribute(
|
|
95
|
+
"data-radius",
|
|
96
|
+
"rounded",
|
|
97
|
+
);
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* A richer example that keeps the default padding: a title, a paragraph and a
|
|
103
|
+
* primary action pushed to the bottom-right corner of the card.
|
|
104
|
+
*/
|
|
105
|
+
export const WithTitleAndAction: Story = {
|
|
106
|
+
args: {
|
|
107
|
+
style: { maxWidth: 360 },
|
|
108
|
+
children: (
|
|
109
|
+
<div
|
|
110
|
+
style={{
|
|
111
|
+
display: "flex",
|
|
112
|
+
flexDirection: "column",
|
|
113
|
+
gap: "var(--spacing-sm)",
|
|
114
|
+
}}
|
|
115
|
+
>
|
|
116
|
+
<h3
|
|
117
|
+
style={{
|
|
118
|
+
margin: 0,
|
|
119
|
+
color: "var(--color-content-neutral-primary)",
|
|
120
|
+
}}
|
|
121
|
+
>
|
|
122
|
+
Card title
|
|
123
|
+
</h3>
|
|
124
|
+
<p
|
|
125
|
+
style={{
|
|
126
|
+
margin: 0,
|
|
127
|
+
color: "var(--color-content-neutral-secondary)",
|
|
128
|
+
}}
|
|
129
|
+
>
|
|
130
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
|
|
131
|
+
eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
|
132
|
+
</p>
|
|
133
|
+
<div style={{ display: "flex", justifyContent: "flex-end" }}>
|
|
134
|
+
<Button text="Voir plus" onClick={() => {}} />
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
),
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* A fully custom layout. The card removes its own padding (`no-padding`) so the
|
|
143
|
+
* children can control everything: a colored header with a white title, and a
|
|
144
|
+
* body with its own padding, a pale bottom-heavy gradient and a decorative icon
|
|
145
|
+
* sitting in the background. `overflow: hidden` keeps the header and gradient
|
|
146
|
+
* clipped to the card radius.
|
|
147
|
+
*/
|
|
148
|
+
export const CustomHeaderAndBackground: Story = {
|
|
149
|
+
args: {
|
|
150
|
+
size: "no-padding",
|
|
151
|
+
style: { maxWidth: 360, overflow: "hidden" },
|
|
152
|
+
children: (
|
|
153
|
+
<>
|
|
154
|
+
<div
|
|
155
|
+
style={{
|
|
156
|
+
background: "var(--color-content-action-action)",
|
|
157
|
+
color: "var(--color-content-neutral-primary-reversed)",
|
|
158
|
+
padding: "var(--spacing-md)",
|
|
159
|
+
}}
|
|
160
|
+
>
|
|
161
|
+
<h3 style={{ margin: 0 }}>Consommation</h3>
|
|
162
|
+
</div>
|
|
163
|
+
<div
|
|
164
|
+
style={{
|
|
165
|
+
position: "relative",
|
|
166
|
+
overflow: "hidden",
|
|
167
|
+
padding: "var(--spacing-md)",
|
|
168
|
+
display: "flex",
|
|
169
|
+
flexDirection: "column",
|
|
170
|
+
gap: "var(--spacing-sm)",
|
|
171
|
+
background:
|
|
172
|
+
"linear-gradient(180deg, var(--color-background-neutral-overground) 0%, var(--color-content-action-action-lighter) 100%)",
|
|
173
|
+
color: "var(--color-content-neutral-primary)",
|
|
174
|
+
}}
|
|
175
|
+
>
|
|
176
|
+
<Icon
|
|
177
|
+
name="bolt"
|
|
178
|
+
style={{
|
|
179
|
+
position: "absolute",
|
|
180
|
+
right: "-12px",
|
|
181
|
+
bottom: "0",
|
|
182
|
+
width: 120,
|
|
183
|
+
height: 120,
|
|
184
|
+
color: "var(--color-content-action-action)",
|
|
185
|
+
opacity: 0.15,
|
|
186
|
+
pointerEvents: "none",
|
|
187
|
+
}}
|
|
188
|
+
/>
|
|
189
|
+
<p style={{ margin: 0, position: "relative" }}>
|
|
190
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suivi de
|
|
191
|
+
votre consommation en temps réel.
|
|
192
|
+
</p>
|
|
193
|
+
<p style={{ margin: 0, position: "relative" }}>
|
|
194
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suivi de
|
|
195
|
+
votre consommation en temps réel.
|
|
196
|
+
</p>
|
|
197
|
+
</div>
|
|
198
|
+
</>
|
|
199
|
+
),
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
```
|
|
@@ -480,6 +480,31 @@ export const ExampleWithLinks: StoryObj<typeof Combobox> = {
|
|
|
480
480
|
},
|
|
481
481
|
};
|
|
482
482
|
|
|
483
|
+
export const ShouldRenderALinkItemWithATarget: StoryObj<typeof Combobox> = {
|
|
484
|
+
args: {
|
|
485
|
+
...Playground.args,
|
|
486
|
+
defaultItems: [
|
|
487
|
+
{ text: "Option 1", id: "1" },
|
|
488
|
+
{
|
|
489
|
+
text: "Google",
|
|
490
|
+
id: "google",
|
|
491
|
+
href: "https://google.com",
|
|
492
|
+
target: "_blank",
|
|
493
|
+
},
|
|
494
|
+
],
|
|
495
|
+
},
|
|
496
|
+
play: async ({ canvasElement }) => {
|
|
497
|
+
const canvas = within(canvasElement);
|
|
498
|
+
const user = userEvent.setup({ delay: 50 });
|
|
499
|
+
await user.type(canvas.getByLabelText("[Insert label]"), "Goo");
|
|
500
|
+
const link = (
|
|
501
|
+
await screen.findByText("Google", { selector: "span" })
|
|
502
|
+
).closest("a");
|
|
503
|
+
await expect(link).toHaveAttribute("href", "https://google.com");
|
|
504
|
+
await expect(link).toHaveAttribute("target", "_blank");
|
|
505
|
+
},
|
|
506
|
+
};
|
|
507
|
+
|
|
483
508
|
export const ExampleWithCustomFiltering: StoryObj<typeof Combobox> = {
|
|
484
509
|
render: () => {
|
|
485
510
|
const options = [
|
|
@@ -7,6 +7,9 @@ export type Props = {
|
|
|
7
7
|
iconLeft?: IconName;
|
|
8
8
|
/**
|
|
9
9
|
* Optional text content for the header. Can also be a React component.
|
|
10
|
+
* Rendered inside the sort button: it must not contain interactive elements
|
|
11
|
+
* (button, link, input), which would be invalid HTML and would trigger the sort
|
|
12
|
+
* on click.
|
|
10
13
|
*/
|
|
11
14
|
text?: React.ReactNode;
|
|
12
15
|
/**
|
|
@@ -14,7 +17,7 @@ export type Props = {
|
|
|
14
17
|
*/
|
|
15
18
|
sortDirection?: "asc" | "desc" | "none";
|
|
16
19
|
/**
|
|
17
|
-
* Callback fired when the
|
|
20
|
+
* Callback fired when the header cell is clicked. If not provided, the header is not sortable and the sort icon is not displayed.
|
|
18
21
|
*/
|
|
19
22
|
onSortClick?: (event?: unknown) => void;
|
|
20
23
|
/**
|
|
@@ -500,7 +500,7 @@ Read [the React Aria blog post](https://react-spectrum.adobe.com/blog/date-and-t
|
|
|
500
500
|
## Value
|
|
501
501
|
|
|
502
502
|
A `DatePicker` displays a placeholder by default. An initial, uncontrolled value can be provided to the `DatePicker` using the `defaultValue` prop.
|
|
503
|
-
Alternatively, a controlled value can be provided using the `value` and `
|
|
503
|
+
Alternatively, a controlled value can be provided using the `value` and `onChange` props.
|
|
504
504
|
|
|
505
505
|
Date values are provided as string.
|
|
506
506
|
This component handles correct international date manipulation across calendars, time zones, and other localization concerns.
|
|
@@ -547,7 +547,7 @@ Read [the React Aria blog post](https://react-spectrum.adobe.com/blog/date-and-t
|
|
|
547
547
|
## Value
|
|
548
548
|
|
|
549
549
|
A `DateRangePicker` displays a placeholder by default. An initial, uncontrolled value can be provided to the `DateRangePicker` using the `defaultValue` prop.
|
|
550
|
-
Alternatively, a controlled value can be provided using the `value` and `
|
|
550
|
+
Alternatively, a controlled value can be provided using the `value` and `onChange` props.
|
|
551
551
|
|
|
552
552
|
Here is the type for the `value` prop (also valid for `defaultValue`, `onChange`, etc.):
|
|
553
553
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HTMLAttributeAnchorTarget } from 'react';
|
|
1
2
|
import { IconName } from '../Icon/Icon';
|
|
2
3
|
export type Props = {
|
|
3
4
|
/**
|
|
@@ -25,6 +26,11 @@ export type Props = {
|
|
|
25
26
|
* A URL to link
|
|
26
27
|
*/
|
|
27
28
|
href?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Only active with the `href` prop.
|
|
31
|
+
* Give a target attribute to use on the rendered anchor.
|
|
32
|
+
*/
|
|
33
|
+
target?: HTMLAttributeAnchorTarget;
|
|
28
34
|
/**
|
|
29
35
|
* Only active with the `href` prop.
|
|
30
36
|
* Router-specific options to pass to the `Link` component under the hood. (configured by the RouterProvider).
|
|
@@ -41,4 +47,4 @@ export type Props = {
|
|
|
41
47
|
*/
|
|
42
48
|
selectionMode?: "single" | "multiple";
|
|
43
49
|
};
|
|
44
|
-
export default function SelectItem({ text, id, iconRight, iconLeft, isSelected, href, routerOptions, className, selectionMode, ...otherProps }: Props): import("react/jsx-runtime").JSX.Element;
|
|
50
|
+
export default function SelectItem({ text, id, iconRight, iconLeft, isSelected, href, target, routerOptions, className, selectionMode, ...otherProps }: Props): import("react/jsx-runtime").JSX.Element;
|
|
@@ -7,7 +7,7 @@ export type Props = Pick<LabelProps, "label" | "labelIconRight" | "labelIconRigh
|
|
|
7
7
|
*/
|
|
8
8
|
id: string;
|
|
9
9
|
/**
|
|
10
|
-
* Actual
|
|
10
|
+
* Actual time value of the TimeField, should be a valid [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Times) time string.
|
|
11
11
|
*/
|
|
12
12
|
value?: string | null;
|
|
13
13
|
/**
|
|
@@ -26,11 +26,12 @@ export type Props = Pick<LabelProps, "label" | "labelIconRight" | "labelIconRigh
|
|
|
26
26
|
*/
|
|
27
27
|
ampm?: boolean;
|
|
28
28
|
/**
|
|
29
|
-
* Determines the smallest unit that is displayed
|
|
29
|
+
* Determines the smallest unit that is displayed by the TimeField, and therefore which segments are editable.
|
|
30
|
+
* @default "minute"
|
|
30
31
|
*/
|
|
31
32
|
granularity?: "hour" | "minute" | "second";
|
|
32
33
|
/**
|
|
33
|
-
* Whether to always show leading zeros in the
|
|
34
|
+
* Whether to always show leading zeros in the hour field. By default, this is determined by the user's locale.
|
|
34
35
|
*/
|
|
35
36
|
shouldForceLeadingZeros?: boolean;
|
|
36
37
|
/**
|
|
@@ -58,10 +59,10 @@ export type Props = Pick<LabelProps, "label" | "labelIconRight" | "labelIconRigh
|
|
|
58
59
|
*/
|
|
59
60
|
style?: React.CSSProperties;
|
|
60
61
|
/**
|
|
61
|
-
* Specifies the nature of the
|
|
62
|
+
* Specifies the nature of the TimeField (mainly to change the input outline color and helperText color).
|
|
62
63
|
* If you do not pass a nature prop, the component will automatically set the nature based on the presence of success/error messages.
|
|
63
64
|
*/
|
|
64
|
-
nature?: "default" | "negative" | "positive";
|
|
65
|
+
nature?: "default" | "negative" | "positive" | "warning";
|
|
65
66
|
/**
|
|
66
67
|
* Props to pass to the wrapper div (for example, style or className).
|
|
67
68
|
*/
|
|
@@ -81,7 +82,7 @@ declare const TimeField: React.ForwardRefExoticComponent<Pick<LabelProps, "label
|
|
|
81
82
|
*/
|
|
82
83
|
id: string;
|
|
83
84
|
/**
|
|
84
|
-
* Actual
|
|
85
|
+
* Actual time value of the TimeField, should be a valid [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Times) time string.
|
|
85
86
|
*/
|
|
86
87
|
value?: string | null;
|
|
87
88
|
/**
|
|
@@ -100,11 +101,12 @@ declare const TimeField: React.ForwardRefExoticComponent<Pick<LabelProps, "label
|
|
|
100
101
|
*/
|
|
101
102
|
ampm?: boolean;
|
|
102
103
|
/**
|
|
103
|
-
* Determines the smallest unit that is displayed
|
|
104
|
+
* Determines the smallest unit that is displayed by the TimeField, and therefore which segments are editable.
|
|
105
|
+
* @default "minute"
|
|
104
106
|
*/
|
|
105
107
|
granularity?: "hour" | "minute" | "second";
|
|
106
108
|
/**
|
|
107
|
-
* Whether to always show leading zeros in the
|
|
109
|
+
* Whether to always show leading zeros in the hour field. By default, this is determined by the user's locale.
|
|
108
110
|
*/
|
|
109
111
|
shouldForceLeadingZeros?: boolean;
|
|
110
112
|
/**
|
|
@@ -132,10 +134,10 @@ declare const TimeField: React.ForwardRefExoticComponent<Pick<LabelProps, "label
|
|
|
132
134
|
*/
|
|
133
135
|
style?: React.CSSProperties;
|
|
134
136
|
/**
|
|
135
|
-
* Specifies the nature of the
|
|
137
|
+
* Specifies the nature of the TimeField (mainly to change the input outline color and helperText color).
|
|
136
138
|
* If you do not pass a nature prop, the component will automatically set the nature based on the presence of success/error messages.
|
|
137
139
|
*/
|
|
138
|
-
nature?: "default" | "negative" | "positive";
|
|
140
|
+
nature?: "default" | "negative" | "positive" | "warning";
|
|
139
141
|
/**
|
|
140
142
|
* Props to pass to the wrapper div (for example, style or className).
|
|
141
143
|
*/
|
|
@@ -16,7 +16,7 @@ Base stories:
|
|
|
16
16
|
import { Meta, StoryObj } from "@storybook/react-vite";
|
|
17
17
|
import TimeField from "./TimeField";
|
|
18
18
|
import { I18nProvider } from "react-aria-components";
|
|
19
|
-
import { fn } from "storybook/test";
|
|
19
|
+
import { expect, fn, within } from "storybook/test";
|
|
20
20
|
|
|
21
21
|
const meta: Meta<typeof TimeField> = {
|
|
22
22
|
component: TimeField,
|
|
@@ -41,6 +41,12 @@ const meta: Meta<typeof TimeField> = {
|
|
|
41
41
|
};
|
|
42
42
|
export default meta;
|
|
43
43
|
|
|
44
|
+
const getRoot = (canvasElement: HTMLElement) =>
|
|
45
|
+
canvasElement.querySelector('[data-design-system-component="TimeField"]');
|
|
46
|
+
|
|
47
|
+
const getInput = (canvasElement: HTMLElement) =>
|
|
48
|
+
canvasElement.querySelector("[data-nature]");
|
|
49
|
+
|
|
44
50
|
export const Playground: StoryObj<typeof TimeField> = {
|
|
45
51
|
args: {
|
|
46
52
|
label: "Time Field",
|
|
@@ -50,6 +56,14 @@ export const Playground: StoryObj<typeof TimeField> = {
|
|
|
50
56
|
labelIconRight: "help_outline",
|
|
51
57
|
labelIconRightTooltip: "Additional information",
|
|
52
58
|
},
|
|
59
|
+
play: async ({ canvasElement }) => {
|
|
60
|
+
const canvas = within(canvasElement);
|
|
61
|
+
await expect(canvas.getByText("Time Field")).toBeVisible();
|
|
62
|
+
await expect(getInput(canvasElement)).toHaveAttribute(
|
|
63
|
+
"data-nature",
|
|
64
|
+
"default",
|
|
65
|
+
);
|
|
66
|
+
},
|
|
53
67
|
};
|
|
54
68
|
|
|
55
69
|
export const Empty: StoryObj<typeof TimeField> = {
|
|
@@ -57,6 +71,13 @@ export const Empty: StoryObj<typeof TimeField> = {
|
|
|
57
71
|
...Playground.args,
|
|
58
72
|
defaultValue: undefined,
|
|
59
73
|
},
|
|
74
|
+
play: async ({ canvasElement }) => {
|
|
75
|
+
const canvas = within(canvasElement);
|
|
76
|
+
await expect(canvas.getByLabelText("hour, Time Field")).toHaveAttribute(
|
|
77
|
+
"data-placeholder",
|
|
78
|
+
"true",
|
|
79
|
+
);
|
|
80
|
+
},
|
|
60
81
|
};
|
|
61
82
|
|
|
62
83
|
export const OnlyHour: StoryObj<typeof TimeField> = {
|
|
@@ -65,6 +86,15 @@ export const OnlyHour: StoryObj<typeof TimeField> = {
|
|
|
65
86
|
defaultValue: "12",
|
|
66
87
|
granularity: "hour",
|
|
67
88
|
},
|
|
89
|
+
play: async ({ canvasElement }) => {
|
|
90
|
+
const canvas = within(canvasElement);
|
|
91
|
+
await expect(canvas.getByLabelText("hour, Time Field")).toHaveTextContent(
|
|
92
|
+
"12",
|
|
93
|
+
);
|
|
94
|
+
await expect(
|
|
95
|
+
canvas.queryByLabelText("minute, Time Field"),
|
|
96
|
+
).not.toBeInTheDocument();
|
|
97
|
+
},
|
|
68
98
|
};
|
|
69
99
|
|
|
70
100
|
export const HourMinute: StoryObj<typeof TimeField> = {
|
|
@@ -73,6 +103,18 @@ export const HourMinute: StoryObj<typeof TimeField> = {
|
|
|
73
103
|
defaultValue: "12:34",
|
|
74
104
|
granularity: "minute",
|
|
75
105
|
},
|
|
106
|
+
play: async ({ canvasElement }) => {
|
|
107
|
+
const canvas = within(canvasElement);
|
|
108
|
+
await expect(canvas.getByLabelText("hour, Time Field")).toHaveTextContent(
|
|
109
|
+
"12",
|
|
110
|
+
);
|
|
111
|
+
await expect(canvas.getByLabelText("minute, Time Field")).toHaveTextContent(
|
|
112
|
+
"34",
|
|
113
|
+
);
|
|
114
|
+
await expect(
|
|
115
|
+
canvas.queryByLabelText("second, Time Field"),
|
|
116
|
+
).not.toBeInTheDocument();
|
|
117
|
+
},
|
|
76
118
|
};
|
|
77
119
|
|
|
78
120
|
export const HourMinuteSecond: StoryObj<typeof TimeField> = {
|
|
@@ -81,6 +123,12 @@ export const HourMinuteSecond: StoryObj<typeof TimeField> = {
|
|
|
81
123
|
defaultValue: "12:34:56",
|
|
82
124
|
granularity: "second",
|
|
83
125
|
},
|
|
126
|
+
play: async ({ canvasElement }) => {
|
|
127
|
+
const canvas = within(canvasElement);
|
|
128
|
+
await expect(canvas.getByLabelText("second, Time Field")).toHaveTextContent(
|
|
129
|
+
"56",
|
|
130
|
+
);
|
|
131
|
+
},
|
|
84
132
|
};
|
|
85
133
|
|
|
86
134
|
export const LocaleFR: StoryObj<typeof TimeField> = {
|
|
@@ -90,6 +138,9 @@ export const LocaleFR: StoryObj<typeof TimeField> = {
|
|
|
90
138
|
args: {
|
|
91
139
|
...HourMinuteSecond.args,
|
|
92
140
|
},
|
|
141
|
+
play: async ({ canvasElement }) => {
|
|
142
|
+
await expect(getInput(canvasElement)).toHaveTextContent("12:34:56");
|
|
143
|
+
},
|
|
93
144
|
};
|
|
94
145
|
|
|
95
146
|
export const Disabled: StoryObj<typeof TimeField> = {
|
|
@@ -97,6 +148,12 @@ export const Disabled: StoryObj<typeof TimeField> = {
|
|
|
97
148
|
...Playground.args,
|
|
98
149
|
isDisabled: true,
|
|
99
150
|
},
|
|
151
|
+
play: async ({ canvasElement }) => {
|
|
152
|
+
await expect(getInput(canvasElement)).toHaveAttribute(
|
|
153
|
+
"aria-disabled",
|
|
154
|
+
"true",
|
|
155
|
+
);
|
|
156
|
+
},
|
|
100
157
|
};
|
|
101
158
|
|
|
102
159
|
export const WithError: StoryObj<typeof TimeField> = {
|
|
@@ -106,6 +163,14 @@ export const WithError: StoryObj<typeof TimeField> = {
|
|
|
106
163
|
errorHelperText: "Error message",
|
|
107
164
|
errorHelperTextIcon: "error_outline",
|
|
108
165
|
},
|
|
166
|
+
play: async ({ canvasElement }) => {
|
|
167
|
+
const canvas = within(canvasElement);
|
|
168
|
+
await expect(canvas.getByText("Error message")).toBeVisible();
|
|
169
|
+
await expect(getInput(canvasElement)).toHaveAttribute(
|
|
170
|
+
"data-nature",
|
|
171
|
+
"negative",
|
|
172
|
+
);
|
|
173
|
+
},
|
|
109
174
|
};
|
|
110
175
|
|
|
111
176
|
export const WithSuccess: StoryObj<typeof TimeField> = {
|
|
@@ -115,6 +180,14 @@ export const WithSuccess: StoryObj<typeof TimeField> = {
|
|
|
115
180
|
successHelperText: "Success message",
|
|
116
181
|
successHelperTextIcon: "check",
|
|
117
182
|
},
|
|
183
|
+
play: async ({ canvasElement }) => {
|
|
184
|
+
const canvas = within(canvasElement);
|
|
185
|
+
await expect(canvas.getByText("Success message")).toBeVisible();
|
|
186
|
+
await expect(getInput(canvasElement)).toHaveAttribute(
|
|
187
|
+
"data-nature",
|
|
188
|
+
"positive",
|
|
189
|
+
);
|
|
190
|
+
},
|
|
118
191
|
};
|
|
119
192
|
|
|
120
193
|
export const WithWarning: StoryObj<typeof TimeField> = {
|
|
@@ -124,6 +197,14 @@ export const WithWarning: StoryObj<typeof TimeField> = {
|
|
|
124
197
|
warningHelperText: "Warning message",
|
|
125
198
|
warningHelperTextIcon: "warning_amber",
|
|
126
199
|
},
|
|
200
|
+
play: async ({ canvasElement }) => {
|
|
201
|
+
const canvas = within(canvasElement);
|
|
202
|
+
await expect(canvas.getByText("Warning message")).toBeVisible();
|
|
203
|
+
await expect(getInput(canvasElement)).toHaveAttribute(
|
|
204
|
+
"data-nature",
|
|
205
|
+
"warning",
|
|
206
|
+
);
|
|
207
|
+
},
|
|
127
208
|
};
|
|
128
209
|
|
|
129
210
|
export const WithHorizontalOrientation: StoryObj<typeof TimeField> = {
|
|
@@ -131,6 +212,11 @@ export const WithHorizontalOrientation: StoryObj<typeof TimeField> = {
|
|
|
131
212
|
...Playground.args,
|
|
132
213
|
orientation: "horizontal",
|
|
133
214
|
},
|
|
215
|
+
play: async ({ canvasElement }) => {
|
|
216
|
+
await expect(
|
|
217
|
+
canvasElement.querySelector("[data-orientation]"),
|
|
218
|
+
).toHaveAttribute("data-orientation", "horizontal");
|
|
219
|
+
},
|
|
134
220
|
};
|
|
135
221
|
|
|
136
222
|
export const FullWidth: StoryObj<typeof TimeField> = {
|
|
@@ -141,6 +227,12 @@ export const FullWidth: StoryObj<typeof TimeField> = {
|
|
|
141
227
|
...Playground.args,
|
|
142
228
|
fullWidth: true,
|
|
143
229
|
},
|
|
230
|
+
play: async ({ canvasElement }) => {
|
|
231
|
+
await expect(getRoot(canvasElement)).toHaveAttribute(
|
|
232
|
+
"data-fullwidth",
|
|
233
|
+
"true",
|
|
234
|
+
);
|
|
235
|
+
},
|
|
144
236
|
};
|
|
145
237
|
```
|
|
146
238
|
|
|
@@ -242,23 +334,23 @@ export const ControlledShouldSelectAValue: StoryObj<typeof TimeField> = {
|
|
|
242
334
|
export const ExampleGranularity: StoryObj<typeof TimeField> = {
|
|
243
335
|
render: () => {
|
|
244
336
|
function Example() {
|
|
245
|
-
const [time,
|
|
337
|
+
const [time, setTime] = useState("12:34");
|
|
246
338
|
|
|
247
339
|
return (
|
|
248
340
|
<>
|
|
249
341
|
<TimeField
|
|
250
|
-
id="
|
|
251
|
-
label="
|
|
342
|
+
id="granularity-second"
|
|
343
|
+
label="Second granularity"
|
|
252
344
|
granularity="second"
|
|
253
345
|
value={time}
|
|
254
|
-
onChange={
|
|
346
|
+
onChange={setTime}
|
|
255
347
|
/>
|
|
256
348
|
<TimeField
|
|
257
|
-
id="
|
|
258
|
-
label="
|
|
349
|
+
id="granularity-hour"
|
|
350
|
+
label="Hour granularity"
|
|
259
351
|
granularity="hour"
|
|
260
352
|
value={time}
|
|
261
|
-
onChange={
|
|
353
|
+
onChange={setTime}
|
|
262
354
|
/>
|
|
263
355
|
</>
|
|
264
356
|
);
|
|
@@ -324,16 +416,24 @@ Read [the React Aria blog post](https://react-spectrum.adobe.com/blog/date-and-t
|
|
|
324
416
|
## Value
|
|
325
417
|
|
|
326
418
|
A `TimeField` displays a placeholder by default. An initial, uncontrolled value can be provided to the `TimeField` using the `defaultValue` prop.
|
|
327
|
-
Alternatively, a controlled value can be provided using the `value` and `
|
|
419
|
+
Alternatively, a controlled value can be provided using the `value` and `onChange` props.
|
|
328
420
|
|
|
329
421
|
Time values are provided as string.
|
|
330
|
-
This component handles correct international time manipulation
|
|
331
|
-
TimeField
|
|
422
|
+
This component handles correct international time manipulation: hour cycle, locale-specific formatting and other localization concerns.
|
|
423
|
+
Values carry no date and no time zone — a `TimeField` holds a plain time of day.
|
|
424
|
+
TimeField accepts values in the following string formats:
|
|
425
|
+
|
|
426
|
+
- `hh`
|
|
427
|
+
- `hh:mm`
|
|
428
|
+
- `hh:mm:ss`
|
|
429
|
+
- `hh:mm:ss.sss`
|
|
430
|
+
|
|
431
|
+
Every format is parsed into a complete time, with the missing units defaulting to zero — `"12"` and `"12:00:00"` are therefore equivalent values.
|
|
432
|
+
|
|
433
|
+
The value format does **not** control what is rendered: the units displayed are decided by the `granularity` prop (see below).
|
|
434
|
+
For example, `value="12:34:56"` with the default `"minute"` granularity displays `12:34`; pass `granularity="second"` to also show the seconds.
|
|
332
435
|
|
|
333
|
-
|
|
334
|
-
- `hh:mm` -> only the hour and minute are displayed
|
|
335
|
-
- `hh:mm:ss` -> only the hour, minute and second are displayed
|
|
336
|
-
- `hh:mm:ss.sss` -> the hour, minute, second and millisecond are displayed (millisecond are not selectable by the user and will not change when the rest of the time is changed)
|
|
436
|
+
Milliseconds are preserved in the value but never displayed, and they are not editable by the user: they will not change when the rest of the time is changed.
|
|
337
437
|
|
|
338
438
|
## Granularity
|
|
339
439
|
|
|
@@ -9,6 +9,7 @@ title: Exhaustive list of all the Design System Components and their props
|
|
|
9
9
|
- [Breadcrumbs](node_modules/@agregio-solutions/design-system/dist/packages/components/Breadcrumbs/doc.md) : A hierarchical navigation path showing the current location in a site structure with collapsible middle items for long paths — use it to help users understand where they are and navigate back to parent sections.
|
|
10
10
|
- [Button](node_modules/@agregio-solutions/design-system/dist/packages/components/Button/doc.md) : An interactive clickable element supporting multiple modes (primary, secondary, tertiary), sizes, and optional icons/badges — use it for form submissions, actions, navigation, or triggering dialogs.
|
|
11
11
|
- [Calendar](node_modules/@agregio-solutions/design-system/dist/packages/components/Calendar/doc.md) : A date picker supporting single selection, date ranges, or multiple selections with customizable constraints and cell rendering — use it to let users visually select one or more dates within an optional date range.
|
|
12
|
+
- [Card](node_modules/@agregio-solutions/design-system/dist/packages/components/Card/doc.md) : A simple container surface with configurable padding size and border radius, extensible via className/style — use it as a base wrapper to group related content into a bounded, elevated block.
|
|
12
13
|
- [ChartLegend](node_modules/@agregio-solutions/design-system/dist/packages/components/ChartLegend/doc.md) : A labeled color bullet (circle, square, or custom shape) optionally clickable to toggle chart series — use it to identify and optionally filter data series in charts.
|
|
13
14
|
- [ChartTooltip](node_modules/@agregio-solutions/design-system/dist/packages/components/ChartTooltip/doc.md) : A structured tooltip with title, colored legend items, optional body section, and footer slot for displaying chart data details — use it to show detailed context when hovering over chart elements.
|
|
14
15
|
- [Checkbox](node_modules/@agregio-solutions/design-system/dist/packages/components/Checkbox/doc.md) : A single checkbox input with optional label, supporting indeterminate state and form submissions — use it for binary on/off selections or as part of a CheckboxGroup for multiple options.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agregio-solutions/design-system",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.96.0",
|
|
4
4
|
"description": "React Component library and Storybook that is part of the Design System for Agregio Solutions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "dist/design-system.js",
|
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
"semantic-release": "semantic-release",
|
|
29
29
|
"prettier:check": "prettier . --check --ignore-path .gitignore",
|
|
30
30
|
"prettier:write": "prettier . --write --ignore-path .gitignore",
|
|
31
|
-
"repomix": "repomix",
|
|
32
31
|
"storybook": "storybook dev -p 6006",
|
|
33
32
|
"storybook:test": "vitest run --project storybook",
|
|
34
33
|
"storybook:test:llm": "DEBUG_PRINT_LIMIT=0 vitest run --project=storybook --reporter=dot --silent --changed --passWithNoTests",
|
|
@@ -80,7 +79,6 @@
|
|
|
80
79
|
"react-router-dom": "7.15.1",
|
|
81
80
|
"recharts": "3.8.1",
|
|
82
81
|
"remark-gfm": "4.0.1",
|
|
83
|
-
"repomix": "1.14.0",
|
|
84
82
|
"semantic-release": "25.0.3",
|
|
85
83
|
"storybook": "10.4.0",
|
|
86
84
|
"typescript-eslint": "8.59.3",
|