@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,579 @@
|
|
|
1
|
+
# DatePicker
|
|
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/DatePicker/DatePicker.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 DatePicker from "./DatePicker";
|
|
18
|
+
import { I18nProvider } from "react-aria-components";
|
|
19
|
+
import { fn } from "storybook/test";
|
|
20
|
+
|
|
21
|
+
const meta: Meta<typeof DatePicker> = {
|
|
22
|
+
component: DatePicker,
|
|
23
|
+
argTypes: {
|
|
24
|
+
label: { control: "text" },
|
|
25
|
+
value: { control: "text" },
|
|
26
|
+
timeZone: {
|
|
27
|
+
control: "select",
|
|
28
|
+
options: ["America/New_York", "Europe/Paris"],
|
|
29
|
+
},
|
|
30
|
+
shouldCloseOnSelect: { control: "boolean" },
|
|
31
|
+
description: { control: "text" },
|
|
32
|
+
helperText: { control: "text" },
|
|
33
|
+
errorHelperText: { control: "text" },
|
|
34
|
+
successHelperText: { control: "text" },
|
|
35
|
+
},
|
|
36
|
+
parameters: {
|
|
37
|
+
layout: "centered",
|
|
38
|
+
},
|
|
39
|
+
decorators: [
|
|
40
|
+
(Story, context) => (
|
|
41
|
+
<I18nProvider locale={context.parameters.locale || "en-EN"}>
|
|
42
|
+
<Story />
|
|
43
|
+
</I18nProvider>
|
|
44
|
+
),
|
|
45
|
+
],
|
|
46
|
+
};
|
|
47
|
+
export default meta;
|
|
48
|
+
|
|
49
|
+
export const Playground: StoryObj<typeof DatePicker> = {
|
|
50
|
+
args: {
|
|
51
|
+
label: "Date Picker",
|
|
52
|
+
id: "date-picker",
|
|
53
|
+
defaultValue: "2020-01-01T12:00:00",
|
|
54
|
+
onChange: fn(),
|
|
55
|
+
labelIconRight: "help_outline",
|
|
56
|
+
labelIconRightTooltip: "Additional information",
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const Empty: StoryObj<typeof DatePicker> = {
|
|
61
|
+
args: {
|
|
62
|
+
...Playground.args,
|
|
63
|
+
defaultValue: undefined,
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
export const WithTime: StoryObj<typeof DatePicker> = {
|
|
67
|
+
args: {
|
|
68
|
+
...Playground.args,
|
|
69
|
+
defaultValue: "2020-01-01T12:00:00",
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const WithTimeZone: StoryObj<typeof DatePicker> = {
|
|
74
|
+
args: {
|
|
75
|
+
...Playground.args,
|
|
76
|
+
defaultValue: "2020-01-01T12:00:00",
|
|
77
|
+
timeZone: "America/New_York",
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const LocaleFR: StoryObj<typeof DatePicker> = {
|
|
82
|
+
parameters: {
|
|
83
|
+
locale: "fr-FR",
|
|
84
|
+
},
|
|
85
|
+
args: {
|
|
86
|
+
...WithTimeZone.args,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const WithMinValue: StoryObj<typeof DatePicker> = {
|
|
91
|
+
args: {
|
|
92
|
+
...Playground.args,
|
|
93
|
+
defaultValue: "2020-01-15",
|
|
94
|
+
minValue: "2020-01-10",
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export const WithMaxValue: StoryObj<typeof DatePicker> = {
|
|
99
|
+
args: {
|
|
100
|
+
...Playground.args,
|
|
101
|
+
defaultValue: "2020-01-08",
|
|
102
|
+
maxValue: "2020-01-10",
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export const Disabled: StoryObj<typeof DatePicker> = {
|
|
107
|
+
args: {
|
|
108
|
+
...Playground.args,
|
|
109
|
+
isDisabled: true,
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export const WithError: StoryObj<typeof DatePicker> = {
|
|
114
|
+
args: {
|
|
115
|
+
...Playground.args,
|
|
116
|
+
helperText: undefined,
|
|
117
|
+
errorHelperText: "Error message",
|
|
118
|
+
errorHelperTextIcon: "error_outline",
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const WithSuccess: StoryObj<typeof DatePicker> = {
|
|
123
|
+
args: {
|
|
124
|
+
...Playground.args,
|
|
125
|
+
helperText: undefined,
|
|
126
|
+
successHelperText: "Success message",
|
|
127
|
+
successHelperTextIcon: "check",
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const WithWarning: StoryObj<typeof DatePicker> = {
|
|
132
|
+
args: {
|
|
133
|
+
...Playground.args,
|
|
134
|
+
helperText: undefined,
|
|
135
|
+
warningHelperText: "Warning message",
|
|
136
|
+
warningHelperTextIcon: "warning_amber",
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export const Horizontal: StoryObj<typeof DatePicker> = {
|
|
141
|
+
args: {
|
|
142
|
+
...Playground.args,
|
|
143
|
+
orientation: "horizontal",
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export const Open: StoryObj<typeof DatePicker> = {
|
|
148
|
+
args: {
|
|
149
|
+
...Playground.args,
|
|
150
|
+
isOpen: true,
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export const FullWidth: StoryObj<typeof DatePicker> = {
|
|
155
|
+
parameters: {
|
|
156
|
+
layout: "padded",
|
|
157
|
+
},
|
|
158
|
+
args: {
|
|
159
|
+
...Playground.args,
|
|
160
|
+
fullWidth: true,
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## How to test this component
|
|
166
|
+
|
|
167
|
+
Here are some more advanced stories with more testing coverage and examples that you can read to understand how to test this component.
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
import { Meta, StoryObj } from "@storybook/react-vite";
|
|
171
|
+
import DatePicker from "../DatePicker";
|
|
172
|
+
import {
|
|
173
|
+
userEvent,
|
|
174
|
+
within,
|
|
175
|
+
screen,
|
|
176
|
+
fireEvent,
|
|
177
|
+
expect,
|
|
178
|
+
fn,
|
|
179
|
+
} from "storybook/test";
|
|
180
|
+
import { I18nProvider } from "react-aria-components";
|
|
181
|
+
import { useState } from "react";
|
|
182
|
+
import { Playground } from "../DatePicker.stories";
|
|
183
|
+
import { useController, useForm } from "react-hook-form";
|
|
184
|
+
|
|
185
|
+
const meta: Meta<typeof DatePicker> = {
|
|
186
|
+
component: DatePicker,
|
|
187
|
+
argTypes: {
|
|
188
|
+
label: { control: "text" },
|
|
189
|
+
},
|
|
190
|
+
parameters: {
|
|
191
|
+
layout: "centered",
|
|
192
|
+
chromatic: { disableSnapshot: true },
|
|
193
|
+
},
|
|
194
|
+
decorators: [
|
|
195
|
+
(Story) => (
|
|
196
|
+
<I18nProvider locale="en-EN">
|
|
197
|
+
<Story />
|
|
198
|
+
</I18nProvider>
|
|
199
|
+
),
|
|
200
|
+
],
|
|
201
|
+
};
|
|
202
|
+
export default meta;
|
|
203
|
+
|
|
204
|
+
type Story = StoryObj<typeof DatePicker>;
|
|
205
|
+
|
|
206
|
+
export const ShouldSelectADateValue: Story = {
|
|
207
|
+
args: {
|
|
208
|
+
...Playground.args,
|
|
209
|
+
onChange: fn(),
|
|
210
|
+
defaultValue: "2020-01-01",
|
|
211
|
+
},
|
|
212
|
+
play: async ({ canvasElement, args }) => {
|
|
213
|
+
const canvas = within(canvasElement);
|
|
214
|
+
const user = userEvent.setup({ delay: 50 });
|
|
215
|
+
await expect(canvas.getByLabelText("month, Date Picker")).toHaveTextContent(
|
|
216
|
+
"1",
|
|
217
|
+
);
|
|
218
|
+
await expect(canvas.getByLabelText("day, Date Picker")).toHaveTextContent(
|
|
219
|
+
"1",
|
|
220
|
+
);
|
|
221
|
+
await expect(canvas.getByLabelText("year, Date Picker")).toHaveTextContent(
|
|
222
|
+
"2020",
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
await user.click(canvas.getByLabelText("Open calendar Date Picker"));
|
|
226
|
+
await screen.findByLabelText("Thursday, January 2, 2020");
|
|
227
|
+
await fireEvent.click(screen.getByLabelText("Thursday, January 2, 2020"));
|
|
228
|
+
await expect(args.onChange).toHaveBeenCalledWith("2020-01-02");
|
|
229
|
+
await expect(canvas.getByLabelText("month, Date Picker")).toHaveTextContent(
|
|
230
|
+
"1",
|
|
231
|
+
);
|
|
232
|
+
await expect(canvas.getByLabelText("day, Date Picker")).toHaveTextContent(
|
|
233
|
+
"2",
|
|
234
|
+
);
|
|
235
|
+
await expect(canvas.getByLabelText("year, Date Picker")).toHaveTextContent(
|
|
236
|
+
"2020",
|
|
237
|
+
);
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
export const ShouldSelectADateTimeValue: Story = {
|
|
242
|
+
args: {
|
|
243
|
+
...Playground.args,
|
|
244
|
+
defaultValue: "2020-01-01T10:00:00",
|
|
245
|
+
},
|
|
246
|
+
play: async ({ canvasElement, args }) => {
|
|
247
|
+
const canvas = within(canvasElement);
|
|
248
|
+
const user = userEvent.setup({ delay: 50 });
|
|
249
|
+
await user.click(canvas.getByLabelText("Open calendar Date Picker"));
|
|
250
|
+
await screen.findByLabelText("Thursday, January 2, 2020");
|
|
251
|
+
await fireEvent.click(screen.getByLabelText("Thursday, January 2, 2020"));
|
|
252
|
+
await expect(args.onChange).toHaveBeenCalledWith("2020-01-02T10:00:00");
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
export const ShouldSelectADateTimeValueWithTimezone: StoryObj<
|
|
257
|
+
typeof DatePicker
|
|
258
|
+
> = {
|
|
259
|
+
args: {
|
|
260
|
+
...Playground.args,
|
|
261
|
+
timeZone: "Europe/Paris",
|
|
262
|
+
defaultValue: "2020-01-01T10:00:00",
|
|
263
|
+
},
|
|
264
|
+
play: async ({ canvasElement, args }) => {
|
|
265
|
+
const canvas = within(canvasElement);
|
|
266
|
+
const user = userEvent.setup({ delay: 50 });
|
|
267
|
+
await user.click(canvas.getByLabelText("Open calendar Date Picker"));
|
|
268
|
+
await screen.findByLabelText("Thursday, January 2, 2020");
|
|
269
|
+
await fireEvent.click(screen.getByLabelText("Thursday, January 2, 2020"));
|
|
270
|
+
await expect(args.onChange).toHaveBeenCalledWith(
|
|
271
|
+
"2020-01-02T09:00:00.000Z",
|
|
272
|
+
);
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
export const ShouldManageThePlaceholdervalueIfATimezoneIsGiven: StoryObj<
|
|
277
|
+
typeof DatePicker
|
|
278
|
+
> = {
|
|
279
|
+
args: {
|
|
280
|
+
...Playground.args,
|
|
281
|
+
defaultValue: undefined,
|
|
282
|
+
timeZone: "Europe/Paris",
|
|
283
|
+
granularity: "minute",
|
|
284
|
+
},
|
|
285
|
+
play: async ({ canvasElement }) => {
|
|
286
|
+
const canvas = within(canvasElement);
|
|
287
|
+
await canvas.findByText("GMT+1");
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
export const ExampleWithReactHookForm: Story = {
|
|
292
|
+
render: () => {
|
|
293
|
+
const ParentComponent = () => {
|
|
294
|
+
const { control } = useForm({
|
|
295
|
+
defaultValues: {
|
|
296
|
+
date: "2020-01-01",
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
const { field } = useController({ control, name: "date" });
|
|
301
|
+
|
|
302
|
+
return (
|
|
303
|
+
<>
|
|
304
|
+
<div>Selected date : {field.value}</div>
|
|
305
|
+
<DatePicker
|
|
306
|
+
{...field}
|
|
307
|
+
id="example-controlled date picker"
|
|
308
|
+
label="Date Picker"
|
|
309
|
+
/>
|
|
310
|
+
</>
|
|
311
|
+
);
|
|
312
|
+
};
|
|
313
|
+
return <ParentComponent />;
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
export const WithReactHookFormShouldSelectAValue: Story = {
|
|
318
|
+
render: ExampleWithReactHookForm.render,
|
|
319
|
+
play: async ({ canvasElement }) => {
|
|
320
|
+
const canvas = within(canvasElement);
|
|
321
|
+
const user = userEvent.setup({ delay: 50 });
|
|
322
|
+
await canvas.findByText("Selected date : 2020-01-01");
|
|
323
|
+
await user.click(canvas.getByLabelText("Open calendar Date Picker"));
|
|
324
|
+
await screen.findByLabelText("Thursday, January 2, 2020");
|
|
325
|
+
await fireEvent.click(screen.getByLabelText("Thursday, January 2, 2020"));
|
|
326
|
+
await canvas.findByText("Selected date : 2020-01-02");
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
export const ExampleGranularity: Story = {
|
|
331
|
+
render: () => {
|
|
332
|
+
function Example() {
|
|
333
|
+
const [date, setDate] = useState("2021-04-07T18:45:22Z");
|
|
334
|
+
|
|
335
|
+
return (
|
|
336
|
+
<>
|
|
337
|
+
<DatePicker
|
|
338
|
+
id="date-and-time"
|
|
339
|
+
label="Date and time"
|
|
340
|
+
granularity="second"
|
|
341
|
+
value={date}
|
|
342
|
+
onChange={setDate}
|
|
343
|
+
/>
|
|
344
|
+
<DatePicker
|
|
345
|
+
id="date"
|
|
346
|
+
label="Date"
|
|
347
|
+
granularity="day"
|
|
348
|
+
value={date}
|
|
349
|
+
onChange={setDate}
|
|
350
|
+
/>
|
|
351
|
+
</>
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
return <Example />;
|
|
355
|
+
},
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
export const ExampleGranularity2: Story = {
|
|
359
|
+
render: () => {
|
|
360
|
+
function Example() {
|
|
361
|
+
return (
|
|
362
|
+
<>
|
|
363
|
+
<DatePicker id="second" label="Event date" granularity="second" />
|
|
364
|
+
<DatePicker id="day" label="Event date" granularity="day" />
|
|
365
|
+
</>
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
return <Example />;
|
|
369
|
+
},
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
export const ExampleInternationalCalendar: Story = {
|
|
373
|
+
render: () => {
|
|
374
|
+
function Example() {
|
|
375
|
+
const [date, setDate] = useState<string | null>(null);
|
|
376
|
+
|
|
377
|
+
return (
|
|
378
|
+
<I18nProvider locale="hi-IN-u-ca-indian">
|
|
379
|
+
<DatePicker
|
|
380
|
+
id="international-calendar"
|
|
381
|
+
label="Date"
|
|
382
|
+
value={date}
|
|
383
|
+
onChange={setDate}
|
|
384
|
+
/>
|
|
385
|
+
<p>Selected date: {date}</p>
|
|
386
|
+
</I18nProvider>
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
return <Example />;
|
|
390
|
+
},
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
export const ExampleMinMax: Story = {
|
|
394
|
+
render: () => {
|
|
395
|
+
return (
|
|
396
|
+
<DatePicker
|
|
397
|
+
id="min-max"
|
|
398
|
+
label="Min Max"
|
|
399
|
+
minValue="2020-01-01"
|
|
400
|
+
maxValue="2020-01-03"
|
|
401
|
+
defaultValue="2020-01-02"
|
|
402
|
+
/>
|
|
403
|
+
);
|
|
404
|
+
},
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
export const ExampleUnavailableDates: Story = {
|
|
408
|
+
render: () => {
|
|
409
|
+
return (
|
|
410
|
+
<DatePicker
|
|
411
|
+
id="unavailable-dates"
|
|
412
|
+
label="Unavailable dates"
|
|
413
|
+
isDateUnavailable={(stringDate) => {
|
|
414
|
+
const date = new Date(stringDate);
|
|
415
|
+
// 0 is Sunday, 6 is Saturday
|
|
416
|
+
if (date.getDay() === 0 || date.getDay() === 6) {
|
|
417
|
+
return true;
|
|
418
|
+
}
|
|
419
|
+
return false;
|
|
420
|
+
}}
|
|
421
|
+
/>
|
|
422
|
+
);
|
|
423
|
+
},
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
export const ShouldBeAbleToChangeTheDateManually: Story = {
|
|
427
|
+
render: () => {
|
|
428
|
+
const ParentComponent = () => {
|
|
429
|
+
const [date, setDate] = useState<string | null>(
|
|
430
|
+
"2020-01-01T10:00:00.000",
|
|
431
|
+
);
|
|
432
|
+
|
|
433
|
+
return (
|
|
434
|
+
<>
|
|
435
|
+
<div>Selected date : {date?.toString()}</div>
|
|
436
|
+
<DatePicker
|
|
437
|
+
id="example-controlled date picker"
|
|
438
|
+
label="Date Picker"
|
|
439
|
+
timeZone="Europe/Paris"
|
|
440
|
+
value={date}
|
|
441
|
+
onChange={setDate}
|
|
442
|
+
/>
|
|
443
|
+
</>
|
|
444
|
+
);
|
|
445
|
+
};
|
|
446
|
+
return <ParentComponent />;
|
|
447
|
+
},
|
|
448
|
+
play: async ({ canvasElement }) => {
|
|
449
|
+
const canvas = within(canvasElement);
|
|
450
|
+
const user = userEvent.setup({ delay: 50 });
|
|
451
|
+
await canvas.findByText("Selected date : 2020-01-01T10:00:00.000");
|
|
452
|
+
await user.type(canvas.getByLabelText("month, Date Picker"), "12");
|
|
453
|
+
await user.type(canvas.getByLabelText("day, Date Picker"), "20");
|
|
454
|
+
await user.type(canvas.getByLabelText("year, Date Picker"), "2021");
|
|
455
|
+
await canvas.findByText("Selected date : 2021-12-20T09:00:00.000Z");
|
|
456
|
+
},
|
|
457
|
+
};
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
## Developer notes
|
|
461
|
+
|
|
462
|
+
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.
|
|
463
|
+
|
|
464
|
+
```mdx
|
|
465
|
+
import {
|
|
466
|
+
Canvas,
|
|
467
|
+
Meta,
|
|
468
|
+
Stories,
|
|
469
|
+
Controls,
|
|
470
|
+
Source,
|
|
471
|
+
Story,
|
|
472
|
+
} from "@storybook/addon-docs/blocks";
|
|
473
|
+
|
|
474
|
+
import * as DatePicker from "./DatePicker.stories";
|
|
475
|
+
import * as DatePickerTests from "./tests/DatePicker.stories";
|
|
476
|
+
|
|
477
|
+
<Meta of={DatePicker} />
|
|
478
|
+
|
|
479
|
+
# DatePicker
|
|
480
|
+
|
|
481
|
+
A date picker combines a DateField and a Calendar popover to allow users to enter or select a date and time value.
|
|
482
|
+
|
|
483
|
+
<Canvas of={DatePicker.Playground} />
|
|
484
|
+
<Controls of={DatePicker.Playground} />
|
|
485
|
+
|
|
486
|
+
## Example (with React Hook Form)
|
|
487
|
+
|
|
488
|
+
<Source of={DatePickerTests.ExampleWithReactHookForm} type="code" dark />
|
|
489
|
+
|
|
490
|
+
A date picker can be built using `<input type="date">`, but this is very limited in functionality, lacking in internationalization capabilities, inconsistent between browsers, and difficult to style. DatePicker helps achieve accessible and international date and time pickers that can be styled as needed.
|
|
491
|
+
|
|
492
|
+
- **Dates and times** – Support for dates and times with configurable granularity.
|
|
493
|
+
- **International** – Support for 13 calendar systems used around the world, including Gregorian, Buddhist, Islamic, Persian, and more. Locale-specific formatting, number systems, hour cycles, and right-to-left support are available as well.
|
|
494
|
+
- **Time zone aware** – Dates and times can optionally include a time zone. All modifications follow time zone rules such as daylight saving time.
|
|
495
|
+
- **Accessible** – Each date and time unit is displayed as an individually focusable and editable segment, which allows users an easy way to edit dates using the keyboard, in any date format and locale. Users can also open a calendar popover to select dates in a standard month grid. Localized screen reader messages are included to announce when the selection and visible date range change.
|
|
496
|
+
- **Touch friendly** – Date segments are editable using an easy to use numeric keypad, and all interactions are accessible using touch-based screen readers.
|
|
497
|
+
|
|
498
|
+
Read [the React Aria blog post](https://react-spectrum.adobe.com/blog/date-and-time-pickers-for-all.html) for more details about the internationalization, accessibility, and user experience features implemented by DatePicker.
|
|
499
|
+
|
|
500
|
+
## Value
|
|
501
|
+
|
|
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 `onchange` props.
|
|
504
|
+
|
|
505
|
+
Date values are provided as string.
|
|
506
|
+
This component handles correct international date manipulation across calendars, time zones, and other localization concerns.
|
|
507
|
+
DatePicker supports values of the following string formats:
|
|
508
|
+
|
|
509
|
+
- `YYYY-MM-DD` -> a date without any time components. Use this type to represent dates where the time is not important, such as a birthday or an all day calendar event.
|
|
510
|
+
- `YYYY-MM-DDTHH:mm:ss` -> a date with a time, but not in any specific time zone. Use this type to represent times that occur at the same local time regardless of the time zone, such as the time of New Years Eve fireworks which always occur at midnight. Most times are better stored with a timezone (see below)
|
|
511
|
+
- `YYYY-MM-DDTHH:mm:ss.000Z` + "Europe/Paris" in `timezone` prop -> ISO 8601 UTC date. Use this type to represent an exact moment in time at a particular location on Earth.
|
|
512
|
+
|
|
513
|
+
## Granularity
|
|
514
|
+
|
|
515
|
+
The granularity prop allows you to control the smallest unit that is displayed by DatePicker.
|
|
516
|
+
By default, dates values are displayed with "day" granularity (year, month, and day) if there is no time part in it, and "minute" granularity if there is a time part.
|
|
517
|
+
More granular time values can be displayed by setting the granularity prop to "second".
|
|
518
|
+
|
|
519
|
+
In addition, when a value with a time is provided but you wish to only display the date, you can set the granularity to "day".
|
|
520
|
+
This has no effect on the actual value (it still has a time component), only on what fields are displayed.
|
|
521
|
+
In the following example, two DatePickers are synchronized with the same value, but display different granularities.
|
|
522
|
+
|
|
523
|
+
<Canvas of={DatePickerTests.ExampleGranularity} sourceState="shown" />
|
|
524
|
+
|
|
525
|
+
If no value or defaultValue prop is passed, then the granularity prop also affects which type of value is emitted from the onChange event.
|
|
526
|
+
|
|
527
|
+
<Canvas of={DatePickerTests.ExampleGranularity2} sourceState="shown" />
|
|
528
|
+
|
|
529
|
+
## International calendar
|
|
530
|
+
|
|
531
|
+
DatePicker supports selecting dates in many calendar systems used around the world, including Gregorian, Hebrew, Indian, Islamic, Buddhist, and more.
|
|
532
|
+
Dates are automatically displayed in the appropriate calendar system for the user's locale.
|
|
533
|
+
The calendar system can be overridden using the [Unicode calendar locale extension](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/calendar#adding_a_calendar_in_the_locale_string), passed to the [I18nProvider](?path=/docs/components-i18nprovider--docs) component.
|
|
534
|
+
|
|
535
|
+
Selected dates passed to onChange always use the same calendar system as the value or defaultValue prop.
|
|
536
|
+
If no value or defaultValue is provided, then dates passed to onChange are always in the Gregorian calendar since this is the most commonly used.
|
|
537
|
+
This means that even though the user selects dates in their local calendar system, applications are able to deal with dates from all users consistently.
|
|
538
|
+
|
|
539
|
+
The below example displays a DatePicker in the Hindi language, using the Indian calendar.
|
|
540
|
+
Dates emitted from onChange are in the Gregorian calendar.
|
|
541
|
+
|
|
542
|
+
<Canvas of={DatePickerTests.ExampleInternationalCalendar} sourceState="shown" />
|
|
543
|
+
|
|
544
|
+
## Minimum and maximum values
|
|
545
|
+
|
|
546
|
+
The `minValue` and `maxValue` props can also be used to ensure the value is within a specific range.
|
|
547
|
+
Here is an example:
|
|
548
|
+
|
|
549
|
+
<Canvas of={DatePickerTests.ExampleMinMax} sourceState="shown" />
|
|
550
|
+
|
|
551
|
+
## Unavailable dates
|
|
552
|
+
|
|
553
|
+
DatePicker supports marking certain dates as unavailable.
|
|
554
|
+
These dates remain focusable with the keyboard in the calendar so that navigation is consistent, but cannot be selected by the user.
|
|
555
|
+
When an unavailable date is entered into the date field, it is marked as invalid (but error message and submission prevention should be made by you on the form level).
|
|
556
|
+
The `isDateUnavailable` prop accepts a callback that is called to evaluate whether each visible date is unavailable.
|
|
557
|
+
|
|
558
|
+
This example show how to mark all week-ends as unavailable.
|
|
559
|
+
|
|
560
|
+
<Canvas of={DatePickerTests.ExampleUnavailableDates} sourceState="shown" />
|
|
561
|
+
|
|
562
|
+
## How to test this component
|
|
563
|
+
|
|
564
|
+
First, click on the button that triggers the calendar opening. It will have a label name formatted like this: `Open calendar ${label}`.
|
|
565
|
+
For example: `getByLabelText("Open calendar Date Picker")` if the component has a label "Date Picker".
|
|
566
|
+
|
|
567
|
+
Second, you need to click on a date. The date will show up in a popup.
|
|
568
|
+
You may need to use `screen.getByLabelText` to target an element inside it. The label will have the corresponding date formatted in the language you provided with the `I18nProvider`.
|
|
569
|
+
|
|
570
|
+
For example, if the locale is "en", you can target a specific date visible in the actual opened calendar using the code `fireEvent.click(screen.getByLabelText("Thursday, January 2, 2020"))`.
|
|
571
|
+
|
|
572
|
+
You may notice that we used `fireEvent` because of a bug with `userEvent` on Firefox for some specific edge cases that (sadly) happen with this calendar.
|
|
573
|
+
|
|
574
|
+
If you want to target any other part of the component, just inspect the rendered HTML and you will see that every targetable element has a dedicated aria-label that you can target with `screen.getByLabelText`.
|
|
575
|
+
|
|
576
|
+
Here is a complete example of one of our tests using Storybook and Testing Library:
|
|
577
|
+
|
|
578
|
+
<Source of={DatePickerTests.ShouldSelectADateValue} type="code" dark />
|
|
579
|
+
```
|