ComponentsForm
Date Range Picker
A date range picker combining a dual-month Calendar with a Radix Popover trigger showing the formatted start–end label.
Default
Disabled
Custom Format
Installation
npx visor add date-range-pickerThis copies two files into your project:
components/ui/date-range-picker/date-range-picker.tsx— the componentcomponents/ui/date-range-picker/date-range-picker.module.css— the styles
Note: Date Range Picker depends on the Calendar component. Install it too:
npx visor add calendarUsage
import { DateRangePicker } from '@/components/ui/date-range-picker/date-range-picker';
import type { DateRange } from 'react-day-picker';
import { useState } from 'react';
export default function Example() {
const [range, setRange] = useState<DateRange>();
return (
<DateRangePicker
value={range}
onChange={setRange}
placeholder="Pick a date range"
/>
);
}API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
value | DateRange | — | The selected date range ({ from, to }). |
onChange | (range: DateRange) => void | — | Callback when the range changes. |
placeholder | string | 'Pick a date range' | Text shown when no range is selected. |
dateFormat | string | 'PPP' | Date format string (date-fns format) used for both endpoints. |
disabled | boolean | false | Disables the date range picker. |
Sub-components
Date Range Picker exports a single component that internally composes a Radix Popover and the Calendar component:
| Component | Element | Purpose |
|---|---|---|
DateRangePicker | <button> (trigger) | Trigger button displaying the selected range or placeholder |
| Internal popover panel | <div> (portal) | Radix PopoverContent containing the two-month calendar |
Calendar | <div> | Dual-month calendar for range selection (installed separately) |
Accessibility
- The trigger button has descriptive text showing either the selected range or placeholder
- When no range is selected, a
<CalendarIcon>provides visual context alongside the placeholder - The popover calendar inherits full keyboard navigation from the Calendar component
- Focus is trapped in the calendar popover when open; Escape closes it and returns focus to the trigger
- The popover remains open after selecting the start date so users can complete the range without reopening
- Pair with a
<Label>and matchinghtmlFor/idin a form context for proper labeling