@tempoxyz/ds 0.3.10 → 0.3.11
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/docs/AGENTS.md +9 -0
- package/dist/docs/components/accordion.md +489 -0
- package/dist/docs/components/address-card.md +147 -0
- package/dist/docs/components/agent-logo.md +194 -0
- package/dist/docs/components/alert-dialog.md +631 -0
- package/dist/docs/components/alert.md +448 -0
- package/dist/docs/components/amount-input.md +305 -0
- package/dist/docs/components/amount.md +794 -0
- package/dist/docs/components/app-shell.md +559 -0
- package/dist/docs/components/asset-chip.md +294 -0
- package/dist/docs/components/autocomplete.md +619 -0
- package/dist/docs/components/avatar.md +321 -0
- package/dist/docs/components/badge.md +339 -0
- package/dist/docs/components/badged-logo.md +116 -0
- package/dist/docs/components/banner.md +379 -0
- package/dist/docs/components/bar-chart.md +208 -0
- package/dist/docs/components/breadcrumbs.md +380 -0
- package/dist/docs/components/button-group.md +286 -0
- package/dist/docs/components/button.md +650 -0
- package/dist/docs/components/calendar.md +375 -0
- package/dist/docs/components/callout.md +96 -0
- package/dist/docs/components/checkbox-group.md +521 -0
- package/dist/docs/components/checkbox.md +467 -0
- package/dist/docs/components/choice-group.md +516 -0
- package/dist/docs/components/choicebox.md +641 -0
- package/dist/docs/components/code.md +100 -0
- package/dist/docs/components/combobox.md +939 -0
- package/dist/docs/components/container.md +257 -0
- package/dist/docs/components/copy-button.md +642 -0
- package/dist/docs/components/date-picker.md +514 -0
- package/dist/docs/components/dialog.md +1332 -0
- package/dist/docs/components/drawer.md +966 -0
- package/dist/docs/components/empty.md +340 -0
- package/dist/docs/components/field.md +570 -0
- package/dist/docs/components/fieldset.md +398 -0
- package/dist/docs/components/frame.md +434 -0
- package/dist/docs/components/gauge.md +299 -0
- package/dist/docs/components/get-started-visual.md +117 -0
- package/dist/docs/components/grid.md +288 -0
- package/dist/docs/components/hero-visual.md +155 -0
- package/dist/docs/components/hex.md +487 -0
- package/dist/docs/components/icon-tile.md +292 -0
- package/dist/docs/components/identicon.md +371 -0
- package/dist/docs/components/inline.md +233 -0
- package/dist/docs/components/inset.md +225 -0
- package/dist/docs/components/kbd.md +423 -0
- package/dist/docs/components/list-group.md +981 -0
- package/dist/docs/components/loading-dots.md +237 -0
- package/dist/docs/components/menu.md +934 -0
- package/dist/docs/components/native-select.md +204 -0
- package/dist/docs/components/network-logo.md +248 -0
- package/dist/docs/components/number-field.md +543 -0
- package/dist/docs/components/otp-field.md +616 -0
- package/dist/docs/components/pagination.md +516 -0
- package/dist/docs/components/popover.md +544 -0
- package/dist/docs/components/progress.md +388 -0
- package/dist/docs/components/qr.md +314 -0
- package/dist/docs/components/radio-group.md +528 -0
- package/dist/docs/components/secret-value.md +406 -0
- package/dist/docs/components/select.md +751 -0
- package/dist/docs/components/separator.md +379 -0
- package/dist/docs/components/sidebar-menu.md +922 -0
- package/dist/docs/components/skeleton.md +517 -0
- package/dist/docs/components/slider.md +539 -0
- package/dist/docs/components/snippet.md +424 -0
- package/dist/docs/components/spinner.md +216 -0
- package/dist/docs/components/split-bar.md +139 -0
- package/dist/docs/components/split-button.md +464 -0
- package/dist/docs/components/stack.md +299 -0
- package/dist/docs/components/status-chip.md +226 -0
- package/dist/docs/components/status-indicator.md +119 -0
- package/dist/docs/components/status-row.md +174 -0
- package/dist/docs/components/stepper.md +451 -0
- package/dist/docs/components/success-hero.md +157 -0
- package/dist/docs/components/surface.md +639 -0
- package/dist/docs/components/switch.md +472 -0
- package/dist/docs/components/table.md +967 -0
- package/dist/docs/components/tabs.md +627 -0
- package/dist/docs/components/tempo-logo.md +185 -0
- package/dist/docs/components/text-input.md +624 -0
- package/dist/docs/components/textarea.md +352 -0
- package/dist/docs/components/toast.md +535 -0
- package/dist/docs/components/token-logo.md +371 -0
- package/dist/docs/components/token.md +247 -0
- package/dist/docs/components/tooltip.md +490 -0
- package/dist/docs/components/verification-code.md +116 -0
- package/dist/docs/components/visual.md +249 -0
- package/dist/docs/components.md +203 -0
- package/dist/docs/foundations/accessibility.md +377 -0
- package/dist/docs/foundations/agents.md +150 -0
- package/dist/docs/foundations/color.md +522 -0
- package/dist/docs/foundations/content/tone.md +194 -0
- package/dist/docs/foundations/content/voice.md +194 -0
- package/dist/docs/foundations/content/writing-style.md +406 -0
- package/dist/docs/foundations/iconography.md +282 -0
- package/dist/docs/foundations/intent.md +360 -0
- package/dist/docs/foundations/layout.md +508 -0
- package/dist/docs/foundations/linter.md +296 -0
- package/dist/docs/foundations/motion.md +151 -0
- package/dist/docs/foundations/radius-and-padding.md +86 -0
- package/dist/docs/foundations/typography.md +266 -0
- package/dist/docs/index.md +137 -0
- package/dist/docs/introduction/faq.md +132 -0
- package/dist/docs/introduction/getting-started.md +377 -0
- package/dist/docs/patterns/blockchain-values.md +709 -0
- package/dist/docs/patterns/dashboards.md +638 -0
- package/dist/docs/patterns/destructive-actions.md +626 -0
- package/dist/docs/patterns/empty-states.md +612 -0
- package/dist/docs/patterns/errors-and-validation.md +808 -0
- package/dist/docs/patterns/feedback-and-status.md +518 -0
- package/dist/docs/patterns/forms.md +679 -0
- package/dist/docs/patterns/loading.md +630 -0
- package/dist/docs/patterns/navigation.md +397 -0
- package/dist/docs/patterns/payments.md +765 -0
- package/dist/docs/patterns/responsive-layout.md +997 -0
- package/dist/docs/patterns/tables-and-lists.md +964 -0
- package/dist/docs/products/tempo-console.md +671 -0
- package/dist/docs/products/tempo-performance.md +437 -0
- package/dist/docs/products/tempo-wallet.md +438 -0
- package/package.json +1 -1
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
# DatePicker
|
|
2
|
+
|
|
3
|
+
Shows the selected date and opens a calendar in a popup.
|
|
4
|
+
|
|
5
|
+
[View source and API](https://github.com/tempoxyz/ds/blob/main/src/web/components/DatePicker.tsx)
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
A date picker is a button that shows the selected date and opens a calendar in a popup. It has no text entry.
|
|
10
|
+
|
|
11
|
+
## Examples
|
|
12
|
+
|
|
13
|
+
### Basic
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { DatePicker } from '@tempoxyz/ds'
|
|
17
|
+
|
|
18
|
+
export function Demo() {
|
|
19
|
+
return (
|
|
20
|
+
<DatePicker.Root>
|
|
21
|
+
<DatePicker.Trigger />
|
|
22
|
+
<DatePicker.Popup>
|
|
23
|
+
<DatePicker.Calendar />
|
|
24
|
+
</DatePicker.Popup>
|
|
25
|
+
</DatePicker.Root>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/DatePicker/Basic.tsx)
|
|
31
|
+
|
|
32
|
+
### Variant
|
|
33
|
+
|
|
34
|
+
Set `variant` on `DatePicker.Trigger` to `filled` (default) or `outlined`.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { DatePicker, style } from '@tempoxyz/ds'
|
|
38
|
+
|
|
39
|
+
export function Demo() {
|
|
40
|
+
return (
|
|
41
|
+
<div {...styles.row()}>
|
|
42
|
+
{(['filled', 'outlined'] as const).map((variant) => (
|
|
43
|
+
<DatePicker.Root key={variant}>
|
|
44
|
+
<DatePicker.Trigger variant={variant} />
|
|
45
|
+
<DatePicker.Popup>
|
|
46
|
+
<DatePicker.Calendar />
|
|
47
|
+
</DatePicker.Popup>
|
|
48
|
+
</DatePicker.Root>
|
|
49
|
+
))}
|
|
50
|
+
</div>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
namespace styles {
|
|
55
|
+
export const row = style({
|
|
56
|
+
alignItems: 'flex-start',
|
|
57
|
+
display: 'flex',
|
|
58
|
+
flexWrap: 'wrap',
|
|
59
|
+
gap: '24',
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/DatePicker/Variant.tsx)
|
|
65
|
+
|
|
66
|
+
### Mode
|
|
67
|
+
|
|
68
|
+
Set `mode="range"` on `DatePicker.Root` to select a range. It defaults to `single`.
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import { DatePicker } from '@tempoxyz/ds'
|
|
72
|
+
|
|
73
|
+
export function Demo() {
|
|
74
|
+
return (
|
|
75
|
+
<DatePicker.Root mode="range">
|
|
76
|
+
<DatePicker.Trigger placeholder="Select range" />
|
|
77
|
+
<DatePicker.Popup>
|
|
78
|
+
<DatePicker.Calendar />
|
|
79
|
+
</DatePicker.Popup>
|
|
80
|
+
</DatePicker.Root>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/DatePicker/Mode.tsx)
|
|
86
|
+
|
|
87
|
+
### Invalid
|
|
88
|
+
|
|
89
|
+
Set `aria-invalid` on `DatePicker.Trigger` to mark it invalid.
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
import { DatePicker } from '@tempoxyz/ds'
|
|
93
|
+
|
|
94
|
+
export function Demo() {
|
|
95
|
+
return (
|
|
96
|
+
<DatePicker.Root>
|
|
97
|
+
<DatePicker.Trigger aria-invalid />
|
|
98
|
+
<DatePicker.Popup>
|
|
99
|
+
<DatePicker.Calendar />
|
|
100
|
+
</DatePicker.Popup>
|
|
101
|
+
</DatePicker.Root>
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/DatePicker/Invalid.tsx)
|
|
107
|
+
|
|
108
|
+
## Anatomy
|
|
109
|
+
|
|
110
|
+
Import the component and assemble its parts.
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
import { DatePicker } from '@tempoxyz/ds'
|
|
114
|
+
|
|
115
|
+
<DatePicker.Root>
|
|
116
|
+
<DatePicker.Trigger />
|
|
117
|
+
<DatePicker.Popup>
|
|
118
|
+
<DatePicker.Calendar />
|
|
119
|
+
</DatePicker.Popup>
|
|
120
|
+
</DatePicker.Root>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Guidelines
|
|
124
|
+
|
|
125
|
+
### When to Use
|
|
126
|
+
|
|
127
|
+
* Enter a date as one field in a form, such as the expiry date of an API key.
|
|
128
|
+
* Enter a range with `mode="range"`, such as the period of a statement export.
|
|
129
|
+
|
|
130
|
+
### When Not to Use
|
|
131
|
+
|
|
132
|
+
* Use [Calendar](/docs/components/calendar) when the grid stays visible, such as in a filter panel.
|
|
133
|
+
* Use [TextInput](/docs/components/text-input) for memorable dates far from today, such as a date of birth.
|
|
134
|
+
* Use [ChoiceGroup](/docs/components/choice-group) or [Select](/docs/components/select) for preset periods, such as 7D or Last 30 days.
|
|
135
|
+
|
|
136
|
+
### Label the Trigger
|
|
137
|
+
|
|
138
|
+
The trigger shows only the date or the placeholder, and `Field.Label` doesn't link to it. Point its `aria-labelledby` at a visible label and at the trigger's own `id`.
|
|
139
|
+
|
|
140
|
+
**Do:** Put a visible label above the trigger and reference it with `aria-labelledby`.
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
/**
|
|
144
|
+
* Do example for "Label the Trigger" on the DatePicker page.
|
|
145
|
+
* Put a visible label above the trigger and reference it with `aria-labelledby`.
|
|
146
|
+
* @module
|
|
147
|
+
*/
|
|
148
|
+
import { DatePicker, style } from '@tempoxyz/ds'
|
|
149
|
+
|
|
150
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
151
|
+
export function Demo() {
|
|
152
|
+
return (
|
|
153
|
+
<div {...styles.field()}>
|
|
154
|
+
<span id="guideline-expiry-label" {...styles.label()}>
|
|
155
|
+
Key expires on
|
|
156
|
+
</span>
|
|
157
|
+
<DatePicker.Root defaultValue={new Date(2027, 0, 31)}>
|
|
158
|
+
<DatePicker.Trigger
|
|
159
|
+
aria-labelledby="guideline-expiry-label guideline-expiry"
|
|
160
|
+
id="guideline-expiry"
|
|
161
|
+
/>
|
|
162
|
+
<DatePicker.Popup>
|
|
163
|
+
<DatePicker.Calendar />
|
|
164
|
+
</DatePicker.Popup>
|
|
165
|
+
</DatePicker.Root>
|
|
166
|
+
</div>
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
namespace styles {
|
|
171
|
+
export const field = style({ display: 'grid', rowGap: '8', width: '100% !custom' })
|
|
172
|
+
|
|
173
|
+
export const label = style({ color: 'content.primary', typography: 'body.b3Strong' })
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Don't:** Leave the trigger to explain itself with Select date.
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
/**
|
|
181
|
+
* Don't example for "Label the Trigger" on the DatePicker page.
|
|
182
|
+
* Don't leave the trigger to explain itself with Select date.
|
|
183
|
+
* @module
|
|
184
|
+
*/
|
|
185
|
+
import { DatePicker, style } from '@tempoxyz/ds'
|
|
186
|
+
|
|
187
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
188
|
+
export function Demo() {
|
|
189
|
+
return (
|
|
190
|
+
<div {...styles.field()}>
|
|
191
|
+
<DatePicker.Root>
|
|
192
|
+
<DatePicker.Trigger />
|
|
193
|
+
<DatePicker.Popup>
|
|
194
|
+
<DatePicker.Calendar />
|
|
195
|
+
</DatePicker.Popup>
|
|
196
|
+
</DatePicker.Root>
|
|
197
|
+
</div>
|
|
198
|
+
)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
namespace styles {
|
|
202
|
+
export const field = style({ display: 'grid', width: '100% !custom' })
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### State Date Limits in Text
|
|
207
|
+
|
|
208
|
+
Pass `min`, `max`, and `isDateDisabled` to `DatePicker.Root`, which passes them to `DatePicker.Calendar`. Describe the limit below the trigger, and point `aria-describedby` at it.
|
|
209
|
+
|
|
210
|
+
**Do:** State the allowed range below the trigger, such as Choose a date within one year.
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
/**
|
|
214
|
+
* Do example for "State Date Limits in Text" on the DatePicker page.
|
|
215
|
+
* State the allowed range below the trigger, such as Choose a date within one year.
|
|
216
|
+
* @module
|
|
217
|
+
*/
|
|
218
|
+
import { DatePicker, style } from '@tempoxyz/ds'
|
|
219
|
+
|
|
220
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
221
|
+
export function Demo() {
|
|
222
|
+
return (
|
|
223
|
+
<div {...styles.field()}>
|
|
224
|
+
<span id="guideline-stated-limit-label" {...styles.label()}>
|
|
225
|
+
Key expires on
|
|
226
|
+
</span>
|
|
227
|
+
<DatePicker.Root max={new Date(2027, 9, 21)} min={new Date(2026, 9, 21)}>
|
|
228
|
+
<DatePicker.Trigger
|
|
229
|
+
aria-labelledby="guideline-stated-limit-label guideline-stated-limit"
|
|
230
|
+
aria-describedby="guideline-stated-limit-hint"
|
|
231
|
+
id="guideline-stated-limit"
|
|
232
|
+
/>
|
|
233
|
+
<DatePicker.Popup>
|
|
234
|
+
<DatePicker.Calendar />
|
|
235
|
+
</DatePicker.Popup>
|
|
236
|
+
</DatePicker.Root>
|
|
237
|
+
<span id="guideline-stated-limit-hint" {...styles.hint()}>
|
|
238
|
+
Choose a date within one year.
|
|
239
|
+
</span>
|
|
240
|
+
</div>
|
|
241
|
+
)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
namespace styles {
|
|
245
|
+
export const field = style({ display: 'grid', rowGap: '8', width: '100% !custom' })
|
|
246
|
+
|
|
247
|
+
export const label = style({ color: 'content.primary', typography: 'body.b3Strong' })
|
|
248
|
+
|
|
249
|
+
export const hint = style({ color: 'content.secondary', typography: 'body.b3' })
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**Don't:** Leave people to find the limit by paging through the calendar.
|
|
254
|
+
|
|
255
|
+
```tsx
|
|
256
|
+
/**
|
|
257
|
+
* Don't example for "State Date Limits in Text" on the DatePicker page.
|
|
258
|
+
* Don't leave people to find the limit by paging through the calendar.
|
|
259
|
+
* @module
|
|
260
|
+
*/
|
|
261
|
+
import { DatePicker, style } from '@tempoxyz/ds'
|
|
262
|
+
|
|
263
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
264
|
+
export function Demo() {
|
|
265
|
+
return (
|
|
266
|
+
<div {...styles.field()}>
|
|
267
|
+
<span id="guideline-unstated-limit-label" {...styles.label()}>
|
|
268
|
+
Key expires on
|
|
269
|
+
</span>
|
|
270
|
+
<DatePicker.Root max={new Date(2027, 9, 21)} min={new Date(2026, 9, 21)}>
|
|
271
|
+
<DatePicker.Trigger
|
|
272
|
+
aria-labelledby="guideline-unstated-limit-label guideline-unstated-limit"
|
|
273
|
+
id="guideline-unstated-limit"
|
|
274
|
+
/>
|
|
275
|
+
<DatePicker.Popup>
|
|
276
|
+
<DatePicker.Calendar />
|
|
277
|
+
</DatePicker.Popup>
|
|
278
|
+
</DatePicker.Root>
|
|
279
|
+
</div>
|
|
280
|
+
)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
namespace styles {
|
|
284
|
+
export const field = style({ display: 'grid', rowGap: '8', width: '100% !custom' })
|
|
285
|
+
|
|
286
|
+
export const label = style({ color: 'content.primary', typography: 'body.b3Strong' })
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Show Errors in Text
|
|
291
|
+
|
|
292
|
+
Set `aria-invalid` on `DatePicker.Trigger` to fill it red. Put the error text below the trigger and point `aria-describedby` at it. `Field.Error` doesn't link to the trigger.
|
|
293
|
+
|
|
294
|
+
**Do:** Pair the red fill with error text that names the fix.
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
/**
|
|
298
|
+
* Do example for "Show Errors in Text" on the DatePicker page.
|
|
299
|
+
* Pair the red fill with error text that names the fix.
|
|
300
|
+
* @module
|
|
301
|
+
*/
|
|
302
|
+
import { DatePicker, style } from '@tempoxyz/ds'
|
|
303
|
+
|
|
304
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
305
|
+
export function Demo() {
|
|
306
|
+
return (
|
|
307
|
+
<div {...styles.field()}>
|
|
308
|
+
<span id="guideline-error-text-label" {...styles.label()}>
|
|
309
|
+
Key expires on
|
|
310
|
+
</span>
|
|
311
|
+
<DatePicker.Root defaultValue={new Date(2026, 9, 1)}>
|
|
312
|
+
<DatePicker.Trigger
|
|
313
|
+
aria-labelledby="guideline-error-text-label guideline-error-text"
|
|
314
|
+
aria-describedby="guideline-error-text-error"
|
|
315
|
+
aria-invalid
|
|
316
|
+
id="guideline-error-text"
|
|
317
|
+
/>
|
|
318
|
+
<DatePicker.Popup>
|
|
319
|
+
<DatePicker.Calendar />
|
|
320
|
+
</DatePicker.Popup>
|
|
321
|
+
</DatePicker.Root>
|
|
322
|
+
<span id="guideline-error-text-error" {...styles.error()}>
|
|
323
|
+
Choose a date after today.
|
|
324
|
+
</span>
|
|
325
|
+
</div>
|
|
326
|
+
)
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
namespace styles {
|
|
330
|
+
export const field = style({ display: 'grid', rowGap: '8', width: '100% !custom' })
|
|
331
|
+
|
|
332
|
+
export const label = style({ color: 'content.primary', typography: 'body.b3Strong' })
|
|
333
|
+
|
|
334
|
+
export const error = style({ color: 'content.negative', typography: 'body.b3' })
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**Don't:** Mark the trigger invalid without saying what is wrong.
|
|
339
|
+
|
|
340
|
+
```tsx
|
|
341
|
+
/**
|
|
342
|
+
* Don't example for "Show Errors in Text" on the DatePicker page.
|
|
343
|
+
* Don't mark the trigger invalid without saying what is wrong.
|
|
344
|
+
* @module
|
|
345
|
+
*/
|
|
346
|
+
import { DatePicker, style } from '@tempoxyz/ds'
|
|
347
|
+
|
|
348
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
349
|
+
export function Demo() {
|
|
350
|
+
return (
|
|
351
|
+
<div {...styles.field()}>
|
|
352
|
+
<span id="guideline-error-ring-label" {...styles.label()}>
|
|
353
|
+
Key expires on
|
|
354
|
+
</span>
|
|
355
|
+
<DatePicker.Root defaultValue={new Date(2026, 9, 1)}>
|
|
356
|
+
<DatePicker.Trigger
|
|
357
|
+
aria-labelledby="guideline-error-ring-label guideline-error-ring"
|
|
358
|
+
aria-invalid
|
|
359
|
+
id="guideline-error-ring"
|
|
360
|
+
/>
|
|
361
|
+
<DatePicker.Popup>
|
|
362
|
+
<DatePicker.Calendar />
|
|
363
|
+
</DatePicker.Popup>
|
|
364
|
+
</DatePicker.Root>
|
|
365
|
+
</div>
|
|
366
|
+
)
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
namespace styles {
|
|
370
|
+
export const field = style({ display: 'grid', rowGap: '8', width: '100% !custom' })
|
|
371
|
+
|
|
372
|
+
export const label = style({ color: 'content.primary', typography: 'body.b3Strong' })
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Match the Fields Around It
|
|
377
|
+
|
|
378
|
+
`DatePicker.Trigger` is as tall as a [TextInput](/docs/components/text-input), at 48px. Use the same variant as the fields beside it.
|
|
379
|
+
|
|
380
|
+
**Do:** Give the trigger the variant of the inputs in the same row.
|
|
381
|
+
|
|
382
|
+
```tsx
|
|
383
|
+
/**
|
|
384
|
+
* Do example for "Match the Fields Around It" on the DatePicker page.
|
|
385
|
+
* Give the trigger the variant of the inputs in the same row.
|
|
386
|
+
* @module
|
|
387
|
+
*/
|
|
388
|
+
import { DatePicker, style, TextInput } from '@tempoxyz/ds'
|
|
389
|
+
|
|
390
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
391
|
+
export function Demo() {
|
|
392
|
+
return (
|
|
393
|
+
<div {...styles.row()}>
|
|
394
|
+
<TextInput.Group {...styles.cell()}>
|
|
395
|
+
<TextInput.Control aria-label="Key name" defaultValue="Checkout server" />
|
|
396
|
+
</TextInput.Group>
|
|
397
|
+
<DatePicker.Root defaultValue={new Date(2027, 0, 31)}>
|
|
398
|
+
<DatePicker.Trigger aria-label="Key expires on" {...styles.cell()} />
|
|
399
|
+
<DatePicker.Popup>
|
|
400
|
+
<DatePicker.Calendar />
|
|
401
|
+
</DatePicker.Popup>
|
|
402
|
+
</DatePicker.Root>
|
|
403
|
+
</div>
|
|
404
|
+
)
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
namespace styles {
|
|
408
|
+
export const cell = style({ flex: '1 !custom', minWidth: '0 !custom' })
|
|
409
|
+
|
|
410
|
+
export const row = style({
|
|
411
|
+
alignItems: 'center',
|
|
412
|
+
display: 'flex',
|
|
413
|
+
gap: '8',
|
|
414
|
+
width: '100% !custom',
|
|
415
|
+
})
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
**Don't:** Mix an `outlined` trigger with filled inputs.
|
|
420
|
+
|
|
421
|
+
```tsx
|
|
422
|
+
/**
|
|
423
|
+
* Don't example for "Match the Fields Around It" on the DatePicker page.
|
|
424
|
+
* Don't mix an `outlined` trigger with filled inputs.
|
|
425
|
+
* @module
|
|
426
|
+
*/
|
|
427
|
+
import { DatePicker, style, TextInput } from '@tempoxyz/ds'
|
|
428
|
+
|
|
429
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
430
|
+
export function Demo() {
|
|
431
|
+
return (
|
|
432
|
+
<div {...styles.row()}>
|
|
433
|
+
<TextInput.Group {...styles.cell()}>
|
|
434
|
+
<TextInput.Control aria-label="Key name" defaultValue="Checkout server" />
|
|
435
|
+
</TextInput.Group>
|
|
436
|
+
<DatePicker.Root defaultValue={new Date(2027, 0, 31)}>
|
|
437
|
+
<DatePicker.Trigger aria-label="Key expires on" variant="outlined" {...styles.cell()} />
|
|
438
|
+
<DatePicker.Popup>
|
|
439
|
+
<DatePicker.Calendar />
|
|
440
|
+
</DatePicker.Popup>
|
|
441
|
+
</DatePicker.Root>
|
|
442
|
+
</div>
|
|
443
|
+
)
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
namespace styles {
|
|
447
|
+
export const cell = style({ flex: '1 !custom', minWidth: '0 !custom' })
|
|
448
|
+
|
|
449
|
+
export const row = style({
|
|
450
|
+
alignItems: 'center',
|
|
451
|
+
display: 'flex',
|
|
452
|
+
gap: '8',
|
|
453
|
+
width: '100% !custom',
|
|
454
|
+
})
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
## Content
|
|
459
|
+
|
|
460
|
+
* **Label:** Name the date, such as Key expires on or Start date.
|
|
461
|
+
* **Placeholder:** Keep Select date in single mode. In range mode, use Select dates.
|
|
462
|
+
* **Value:** The trigger formats it with `Intl.DateTimeFormat` in the medium date style for `locale`, such as Jan 31, 2027, and a range as one span.
|
|
463
|
+
|
|
464
|
+
## Accessibility
|
|
465
|
+
|
|
466
|
+
A date picker renders a button that opens a calendar in a popup dialog. It follows the [WAI-ARIA Authoring Practices date picker dialog example](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepicker-dialog/), except that the popup is not modal.
|
|
467
|
+
|
|
468
|
+
### Semantics
|
|
469
|
+
|
|
470
|
+
* **DatePicker.Trigger (button):** Announces that it opens a dialog, and whether the dialog is open.
|
|
471
|
+
* **DatePicker.Popup (dialog):** Renders a `dialog` named "Choose date" unless you pass `aria-label`.
|
|
472
|
+
* **DatePicker.Calendar (grid):** Uses the grid semantics described on [Calendar](/docs/components/calendar#accessibility).
|
|
473
|
+
* **Target Size (48px):** The trigger is above the 24px WCAG 2.2 minimum.
|
|
474
|
+
|
|
475
|
+
### Keyboard
|
|
476
|
+
|
|
477
|
+
* **Move Focus to the Trigger (Tab):** Moves focus to the trigger.
|
|
478
|
+
* **Open the Popup (Enter or Space):** On the trigger, opens the popup and focuses a day.
|
|
479
|
+
* **Move Through Dates (Arrow keys):** Home, End, Page Up, and Page Down also move, as on [Calendar](/docs/components/calendar#keyboard).
|
|
480
|
+
* **Select a Day (Enter or Space):** On a day, selects it and closes the popup. In `range` mode, the popup closes after the end date.
|
|
481
|
+
* **Move Within the Popup (Tab and Shift+Tab):** Move between the month buttons and the day grid.
|
|
482
|
+
* **Close the Popup (Escape):** Closes the popup without a change, and returns focus to the trigger.
|
|
483
|
+
|
|
484
|
+
### Focus
|
|
485
|
+
|
|
486
|
+
When the popup opens, focus moves to the selected day, or today. The popup doesn't trap focus, so Tab can leave it.
|
|
487
|
+
|
|
488
|
+
### Your Responsibilities
|
|
489
|
+
|
|
490
|
+
* **Name the Trigger (aria-labelledby):** Point it at the visible label and the trigger, so the name includes the date.
|
|
491
|
+
* **Name Each Popup (aria-label):** If a page has several pickers, name each popup, such as "Choose start date".
|
|
492
|
+
* **Link the Error Text (aria-describedby):** Point it at the error text below the trigger.
|
|
493
|
+
|
|
494
|
+
## Related
|
|
495
|
+
|
|
496
|
+
[Calendar](/docs/components/calendar)
|
|
497
|
+
|
|
498
|
+
Use for an inline month grid.
|
|
499
|
+
|
|
500
|
+
[TextInput](/docs/components/text-input)
|
|
501
|
+
|
|
502
|
+
Use for typed and native dates.
|
|
503
|
+
|
|
504
|
+
[Popover](/docs/components/popover)
|
|
505
|
+
|
|
506
|
+
Use for other anchored popups.
|
|
507
|
+
|
|
508
|
+
[Field](/docs/components/field)
|
|
509
|
+
|
|
510
|
+
Use for labels and errors on other controls.
|
|
511
|
+
|
|
512
|
+
[Forms](/docs/patterns/forms)
|
|
513
|
+
|
|
514
|
+
Covers placing a date among other fields.
|