0
# Selection System
1
2
React Day Picker provides a type-safe selection system supporting single date, multiple dates, and date range selection with both controlled and uncontrolled modes.
3
4
## Capabilities
5
6
### Selection Modes
7
8
The library supports three main selection modes with optional required validation.
9
10
```typescript { .api }
11
/**
12
* Selection mode types
13
*/
14
type Mode = "single" | "multiple" | "range";
15
16
/**
17
* Type-safe selected value based on selection mode
18
*/
19
type SelectedValue<T extends DayPickerProps> =
20
T["mode"] extends "single" ? Date | undefined :
21
T["mode"] extends "multiple" ? Date[] | undefined :
22
T["mode"] extends "range" ? DateRange | undefined :
23
never;
24
25
/**
26
* Type-safe selection handler based on selection mode
27
*/
28
type SelectHandler<T extends DayPickerProps> = (
29
value: SelectedValue<T>,
30
triggerDate: Date,
31
modifiers: Modifiers,
32
e: React.MouseEvent
33
) => void;
34
```
35
36
### Single Date Selection
37
38
Select a single date from the calendar.
39
40
```typescript { .api }
41
/**
42
* Props for single date selection mode
43
*/
44
interface PropsSingle {
45
mode: "single";
46
/** The selected date */
47
selected?: Date;
48
/** The default selected date for uncontrolled mode */
49
defaultSelected?: Date;
50
/** Event handler when a date is selected */
51
onSelect?: (
52
date: Date | undefined,
53
triggerDate: Date,
54
modifiers: Modifiers,
55
e: React.MouseEvent
56
) => void;
57
}
58
59
/**
60
* Props for required single date selection
61
*/
62
interface PropsSingleRequired {
63
mode: "single";
64
required: true;
65
/** The selected date (required) */
66
selected?: Date;
67
/** The default selected date for uncontrolled mode (required) */
68
defaultSelected?: Date;
69
/** Event handler when a date is selected (cannot be undefined) */
70
onSelect?: (
71
date: Date,
72
triggerDate: Date,
73
modifiers: Modifiers,
74
e: React.MouseEvent
75
) => void;
76
}
77
```
78
79
**Usage Examples:**
80
81
```typescript
82
import React, { useState } from "react";
83
import { DayPicker } from "react-day-picker";
84
85
// Controlled single selection
86
function ControlledSingle() {
87
const [selected, setSelected] = useState<Date>();
88
89
return (
90
<DayPicker
91
mode="single"
92
selected={selected}
93
onSelect={setSelected}
94
/>
95
);
96
}
97
98
// Uncontrolled single selection
99
function UncontrolledSingle() {
100
return (
101
<DayPicker
102
mode="single"
103
defaultSelected={new Date()}
104
onSelect={(date) => console.log("Selected:", date)}
105
/>
106
);
107
}
108
109
// Required single selection
110
function RequiredSingle() {
111
const [selected, setSelected] = useState<Date>(new Date());
112
113
return (
114
<DayPicker
115
mode="single"
116
required
117
selected={selected}
118
onSelect={setSelected}
119
/>
120
);
121
}
122
```
123
124
### Multiple Date Selection
125
126
Select multiple individual dates from the calendar.
127
128
```typescript { .api }
129
/**
130
* Props for multiple date selection mode
131
*/
132
interface PropsMulti {
133
mode: "multiple";
134
/** The selected dates array */
135
selected?: Date[];
136
/** The default selected dates for uncontrolled mode */
137
defaultSelected?: Date[];
138
/** Minimum number of dates that must be selected */
139
min?: number;
140
/** Maximum number of dates that can be selected */
141
max?: number;
142
/** Event handler when dates are selected */
143
onSelect?: (
144
dates: Date[] | undefined,
145
triggerDate: Date,
146
modifiers: Modifiers,
147
e: React.MouseEvent
148
) => void;
149
}
150
151
/**
152
* Props for required multiple date selection
153
*/
154
interface PropsMultiRequired {
155
mode: "multiple";
156
required: true;
157
/** The selected dates array (required) */
158
selected?: Date[];
159
/** The default selected dates for uncontrolled mode (required) */
160
defaultSelected?: Date[];
161
/** Minimum number of dates that must be selected */
162
min?: number;
163
/** Maximum number of dates that can be selected */
164
max?: number;
165
/** Event handler when dates are selected (cannot be empty) */
166
onSelect?: (
167
dates: Date[],
168
triggerDate: Date,
169
modifiers: Modifiers,
170
e: React.MouseEvent
171
) => void;
172
}
173
```
174
175
**Usage Examples:**
176
177
```typescript
178
// Controlled multiple selection
179
function ControlledMultiple() {
180
const [selected, setSelected] = useState<Date[]>([]);
181
182
return (
183
<DayPicker
184
mode="multiple"
185
selected={selected}
186
onSelect={setSelected}
187
max={5} // limit to 5 dates
188
/>
189
);
190
}
191
192
// Multiple selection with constraints
193
function ConstrainedMultiple() {
194
const [selected, setSelected] = useState<Date[]>([]);
195
196
return (
197
<DayPicker
198
mode="multiple"
199
selected={selected}
200
onSelect={setSelected}
201
min={2}
202
max={7}
203
disabled={{ dayOfWeek: [0, 6] }} // disable weekends
204
/>
205
);
206
}
207
```
208
209
### Date Range Selection
210
211
Select a continuous range of dates with start and end dates.
212
213
```typescript { .api }
214
/**
215
* Props for date range selection mode
216
*/
217
interface PropsRange {
218
mode: "range";
219
/** The selected date range */
220
selected?: DateRange;
221
/** The default selected range for uncontrolled mode */
222
defaultSelected?: DateRange;
223
/** Minimum number of days in the range */
224
min?: number;
225
/** Maximum number of days in the range */
226
max?: number;
227
/** Event handler when a range is selected */
228
onSelect?: (
229
range: DateRange | undefined,
230
triggerDate: Date,
231
modifiers: Modifiers,
232
e: React.MouseEvent
233
) => void;
234
}
235
236
/**
237
* Props for required date range selection
238
*/
239
interface PropsRangeRequired {
240
mode: "range";
241
required: true;
242
/** The selected date range (required) */
243
selected?: DateRange;
244
/** The default selected range for uncontrolled mode (required) */
245
defaultSelected?: DateRange;
246
/** Minimum number of days in the range */
247
min?: number;
248
/** Maximum number of days in the range */
249
max?: number;
250
/** Event handler when a range is selected (cannot be undefined) */
251
onSelect?: (
252
range: DateRange,
253
triggerDate: Date,
254
modifiers: Modifiers,
255
e: React.MouseEvent
256
) => void;
257
}
258
259
/**
260
* Date range interface
261
*/
262
interface DateRange {
263
from: Date | undefined;
264
to?: Date | undefined;
265
}
266
```
267
268
**Usage Examples:**
269
270
```typescript
271
// Controlled range selection
272
function ControlledRange() {
273
const [range, setRange] = useState<DateRange | undefined>();
274
275
return (
276
<DayPicker
277
mode="range"
278
selected={range}
279
onSelect={setRange}
280
numberOfMonths={2}
281
/>
282
);
283
}
284
285
// Range selection with constraints
286
function ConstrainedRange() {
287
const [range, setRange] = useState<DateRange | undefined>();
288
289
const handleSelect = (newRange: DateRange | undefined) => {
290
// Custom validation logic
291
if (newRange?.from && newRange?.to) {
292
const daysDiff = Math.abs(
293
newRange.to.getTime() - newRange.from.getTime()
294
) / (1000 * 60 * 60 * 24);
295
296
if (daysDiff > 14) {
297
alert("Range cannot exceed 14 days");
298
return;
299
}
300
}
301
setRange(newRange);
302
};
303
304
return (
305
<DayPicker
306
mode="range"
307
selected={range}
308
onSelect={handleSelect}
309
min={3} // minimum 3 days
310
max={14} // maximum 14 days
311
/>
312
);
313
}
314
315
// Range selection with custom styling
316
function StyledRange() {
317
const [range, setRange] = useState<DateRange | undefined>();
318
319
return (
320
<DayPicker
321
mode="range"
322
selected={range}
323
onSelect={setRange}
324
modifiersClassNames={{
325
range_start: "range-start",
326
range_middle: "range-middle",
327
range_end: "range-end"
328
}}
329
/>
330
);
331
}
332
```
333
334
### Selection Context Hook
335
336
Hook for accessing selection state in custom components.
337
338
```typescript { .api }
339
/**
340
* Hook providing access to the DayPicker context
341
* @returns DayPicker context with selection state and handlers
342
*/
343
function useDayPicker<T extends DayPickerProps>(): DayPickerContext<T>;
344
345
interface DayPickerContext<T extends DayPickerProps> {
346
/** The DayPicker props */
347
dayPickerProps: T;
348
/** Current selected value */
349
selected: SelectedValue<T>;
350
/** Selection handler function */
351
select: SelectHandler<T>;
352
/** Function to check if a date is selected */
353
isSelected?: (date: Date) => boolean;
354
/** Calendar months data */
355
months: CalendarMonth[];
356
/** Next navigable month */
357
nextMonth?: Date;
358
/** Previous navigable month */
359
previousMonth?: Date;
360
/** Navigate to specific month */
361
goToMonth: (month: Date) => void;
362
/** Get modifiers for a day */
363
getModifiers: (day: CalendarDay) => Modifiers;
364
/** Custom components */
365
components: CustomComponents;
366
/** CSS class names */
367
classNames: ClassNames;
368
/** CSS styles */
369
styles?: Partial<Styles>;
370
/** Accessibility labels */
371
labels: Labels;
372
/** Date formatters */
373
formatters: Formatters;
374
}
375
```
376
377
**Usage Example:**
378
379
```typescript
380
import { useDayPicker } from "react-day-picker";
381
382
function CustomFooter() {
383
const { selected, mode } = useDayPicker();
384
385
if (mode === "single" && selected) {
386
return <p>Selected: {selected.toDateString()}</p>;
387
}
388
389
if (mode === "range" && selected?.from) {
390
return (
391
<p>
392
{selected.from.toDateString()}
393
{selected.to ? ` - ${selected.to.toDateString()}` : " (select end date)"}
394
</p>
395
);
396
}
397
398
return <p>No date selected</p>;
399
}
400
401
// Usage in DayPicker
402
<DayPicker
403
mode="single"
404
components={{ Footer: CustomFooter }}
405
/>
406
```