DateRangePicker
A field that opens a month, and takes two days from it.
Overview
A field that opens a month, and takes two days from it.
First example
<DateRangePicker value={stay} onValueChange={setStay}><DateRangePicker.Trigger><DateRangePicker.Value placeholder="Choisir un séjour" /><DateRangePicker.Indicator /></DateRangePicker.Trigger><DateRangePicker.Sheet previousLabel="Mois précédent" nextLabel="Mois suivant" /></DateRangePicker>
Anatomy
<DateRangePicker>
<DateRangePicker.Calendar />
<DateRangePicker.Sheet />
<DateRangePicker.Trigger />
<DateRangePicker.Value />
</DateRangePicker>
Usage
<DateRangePicker value={stay} onValueChange={setStay}>
<DateRangePicker.Trigger>
<DateRangePicker.Value placeholder="Choisir un séjour" />
<DateRangePicker.Indicator />
</DateRangePicker.Trigger>
<DateRangePicker.Sheet previousLabel="Mois précédent" nextLabel="Mois suivant" />
</DateRangePicker>
Root props
DateRangePickerProps
The node's inherited React Native props apply too, and so do its style props — padding, margin, width and the rest.
| Prop | Type | Required | Description |
|---|---|---|---|
| variant | DateRangePickerVariant | undefined | No | Dresses the **field**. `calendarVariant` dresses the month. |
| size | DateRangePickerSize | undefined | No | — |
| radius | RadiusKey | undefined | No | — |
| color | string | undefined | No | — |
| calendarVariant | CalendarVariant | undefined | No | The month's own level. A `ghost` field over a `primary` month is the ordinary case. |
| value | DateRange | undefined | No | The period chosen. Controlled — leave it out and the picker holds its own. |
| defaultValue | DateRange | undefined | No | — |
| onValueChange | ((value: DateRange) => void) | undefined | No | — |
| isOpen | boolean | undefined | No | — |
| defaultOpen | boolean | undefined | No | — |
| onOpenChange | ((isOpen: boolean) => void) | undefined | No | — |
| minValue | Date | undefined | No | — |
| maxValue | Date | undefined | No | — |
| firstDayOfWeek | WeekDay | undefined | No | — |
| locale | string | undefined | No | — |
| formatOptions | DateTimeFormatOptions | undefined | No | How each end reads in the field. |
| separator | string | undefined | No | What is written between the two ends in the field. |
| closeOnSelect | boolean | undefined | No | Whether closing the **second** end closes the sheet. The first never does: a period is two decisions, and a sheet that shut after the first would make the second one a second opening. |
| isDisabled | boolean | undefined | No | — |
| isInvalid | boolean | undefined | No | — |
| children | ReactNode | No | — |
Slots
DateRangePickerCalendarProps
The node's inherited React Native props apply too, and so do its style props — padding, margin, width and the rest.
| Prop | Type | Required | Description |
|---|---|---|---|
| previousLabel | string | undefined | No | — |
| nextLabel | string | undefined | No | — |
DateRangePickerSheetProps
The node's inherited React Native props apply too, and so do its style props — padding, margin, width and the rest.
| Prop | Type | Required | Description |
|---|---|---|---|
| previousLabel | string | undefined | No | The month's two arrows, as on the `Calendar` itself. |
| nextLabel | string | undefined | No | — |
DateRangePickerTriggerProps
The node's inherited React Native props apply too, and so do its style props — padding, margin, width and the rest.
| Prop | Type | Required | Description |
|---|---|---|---|
| asChild | boolean | undefined | No | Merge into the single child instead of rendering a pressable (R12) — **keeping the feedback**. Swapping this component out for a bare `Slot` would silently drop the touch feedback of every `asChild` control. |
| children | ReactNode | No | — |
| style | StyleProp<ViewStyle> | ((state: PressableStateCallbackType) => StyleProp<ViewStyle>) | No | R9 — `Pressable`'s function form as much as an object or an array. |
DateRangePickerValueProps
The node's inherited React Native props apply too, and so do its style props — padding, margin, width and the rest.
| Prop | Type | Required | Description |
|---|---|---|---|
| children | ReactNode | No | — |
| placeholder | string | undefined | No | What the field says with no period chosen. |
Variants, sizes and colour
variant dresses the field, calendarVariant dresses the month
A ghost field over a primary month is the ordinary case — the trigger is quiet on the form
and the chosen period is not.
minValue, maxValue, firstDayOfWeek and locale pass straight through.
formatOptions is Intl.DateTimeFormatOptions and reads each end with it.
The root renders no node: ref, style and the a11y props live on
DateRangePicker.Trigger.
Accessibility
Migration from legacy
Implementation notes
It owns almost nothing
The trigger is a Select's trigger and the month is a RangeCalendar, which is
itself a Calendar. What this adds is the wiring: two ends read into the field through
Intl, and a sheet that closes on the second one.
Every rule the RangeCalendar has — the third press, the backwards range, the one-day range
— is this component's too, because it is that component.
A sheet rather than an anchored panel, for the TimePicker's reason: a month is three
hundred points wide, which beside a field on a phone is the screen.
The first choice never closes the sheet
A period is two decisions, and a sheet that shut after the first would make the second one
a second opening. closeOnSelect governs the second only.
A start with no end reads as itself
Not as "start – ". A dash with nothing after it says the field is broken, where a lone date
says it is half answered — which is exactly what it is between the two presses.
The separator is an en dash with a space either side, not a hyphen: a hyphen is already the date separator in half the locales this field serves.
See also
DateRangeField— a period typed rather than chosen.RangeCalendar— the month on its own.DatePicker— one day rather than two.