Acronis UIKit
Components

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

Edit on GitHub

On this page