DateRangePicker
A date-field trigger that opens a dual-month range calendar panel.
Usage
import { DateRangePicker } from '@acronis-platform/ui-react';DateRangePicker composes an InputDatePicker
trigger (pickerType="dateRange") with a Popover holding
a dual-month range CalendarPanel
(variant="range"). It follows a draft/commit/revert model: the applied range is
snapshotted into a draft on open; selecting days in the calendar mutates only that
draft; dismissing the popover reverts it. The footer — Cancel / Apply — is
CalendarPanel's own: Cancel reverts the draft and closes, Apply commits
the range via onValueChange and closes. Apply is never disabled, so it can
commit an empty ({ from: undefined, to: undefined }) or half-open range if
pressed before a full range is picked. Use value for controlled usage or
defaultValue for uncontrolled.
The calendar's selection constraints and every string the popup renders on its own
are forwarded to that CalendarPanel: disabledDays, min, max,
showOutsideDays, weekStartsOn, fromYear, toYear, locale, monthLabel,
yearLabel, formatMonthLabel, cancelLabel and applyLabel. disabledDays is
CalendarPanel's disabled renamed, because disabled here disables the trigger.
There is no dir prop — the ambient text direction is read from the document
(useDocDir()) and passed down, since the day grid needs dir directly for
its Arrow Left/Right roaming.
The trigger reads dates back in its own fixed MMM d, yyyy format; locale
translates that month name too, but the day/year order stays fixed —
locale-aware reordering of the trigger's date isn't supported yet.
It owns no dedicated token tier of its own — the trigger brings
--ui-input-date-picker-* and the popup is themed by the composed
CalendarPanel (--ui-calendar-*). Popover contributes only positioning,
portaling and dismissal — its own container chrome (border, radius, shadow,
background) is neutralized so CalendarPanel's own chrome shows through
instead (presets are intentionally out of scope for v1).
className is forwarded straight into InputDatePicker's trigger field, so it
targets the field as a whole (label, box, and message together) — not the
popover or calendar panel — and sizes correctly in a flex/grid ancestor.
Examples
Uncontrolled, defaulting to the first half of July:
<DateRangePicker
label="Period"
placeholder="Select a date range"
defaultValue={{ from: new Date(2026, 6, 1), to: new Date(2026, 6, 15) }}
onValueChange={(range) => console.log(range)}
/>Controlled — the parent owns the applied range:
const [range, setRange] = React.useState<DateRange>({
from: new Date(2026, 6, 10),
to: new Date(2026, 6, 20),
});
<DateRangePicker label="Period" value={range} onValueChange={setRange} />Required, with an error message:
<DateRangePicker label="Period" required placeholder="Select a date range" />
<DateRangePicker label="Period" error="Please select a valid date range." />Localized, with the calendar limited to past dates and a 31-night maximum span
(up to 32 selectable days — max counts nights between the range's start and
end, not selectable days):
import { es } from 'react-day-picker/locale';
<DateRangePicker
label="Período"
placeholder="Selecciona un rango de fechas"
locale={es}
monthLabel="Mes"
yearLabel="Año"
cancelLabel="Cancelar"
applyLabel="Aplicar"
disabledDays={{ after: new Date() }}
max={31}
onValueChange={setRange}
/>API Reference
Prop
Type