Start and end date fields with a two-month calendar and optional presets like 'Last 7 days'.
import { DateRangePicker } from "@rdloom/react";
export default function DateRangePickerBasicExample() {
return (
<DateRangePicker className="w-80" label="Report period" />
);
}Installation
npx rdloom add date-range-pickerCopies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes. It needs @internationalized/date, react-aria-components; add --install to install them.
Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/date-range-picker.jsonWorks, but without upgrade tracking.
Usage
import { DateRangePicker } from "@rdloom/react";
<DateRangePicker className="w-80" label="Report period" />With presets
import { DateRangePicker, defaultDateRangePresets } from "@rdloom/react";
export default function DateRangePickerWithPresetsExample() {
return (
<DateRangePicker className="w-80" label="Report period" presets={defaultDateRangePresets} />
);
}Time zone
import { DateRangePicker, defaultDateRangePresets } from "@rdloom/react";
export default function DateRangePickerTimeZoneExample() {
return (
<DateRangePicker
className="w-80"
label="Tokyo office hours"
description="Presets like Today use Tokyo's date"
presets={defaultDateRangePresets}
timeZone="Asia/Tokyo"
/>
);
}Min max
import { getLocalTimeZone, today } from "@internationalized/date";
import { DateRangePicker } from "@rdloom/react";
export default function DateRangePickerMinMaxExample() {
const now = today(getLocalTimeZone());
return (
<DateRangePicker className="w-80" label="Booking" description="Up to 60 days ahead" minValue={now} maxValue={now.add({ days: 60 })} />
);
}API Reference
Defined by the spec. Components also accept the props of the React Aria component they wrap.
| Prop | Type | Default |
|---|---|---|
labelrequiredVisible label. | string | none |
descriptionHelp text under the field. | string | none |
errorMessageShown when the range is invalid. | string | none |
sizeField height and font size. | "sm" | "md" | "lg" | "md" |
presetsQuick ranges shown beside the calendar. Pass defaultDateRangePresets or your own. | DateRangePreset[] | none |
timeZoneIANA time zone that presets use for 'today'. Defaults to the user's local zone. | string | none |
visibleMonthsMonths shown in the popover. | number | 2 |
valueControlled range. | DateRange | null | none |
defaultValueInitial range when uncontrolled. | DateRange | none |
minValueEarliest allowed date. | DateValue | none |
maxValueLatest allowed date. | DateValue | none |
isDisabledPrevents editing and dims the field. | boolean | false |
isInvalidMarks the range invalid and shows errorMessage. | boolean | false |
isRequiredRequires a range for form submission. | boolean | false |
onChangeCalled when the range changes, including from a preset. | (value: DateRange | null) => void | none |
Accessibility
Role group, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.
Keyboard
- Tab moves between start and end segments
- Up/Down arrows change the focused segment
- Alt+Down opens the calendar, Esc closes it
- Presets are buttons reachable with Tab
Screen readers announce
- Start and end segments are distinguishable (start date / end date)
- Presets are announced as buttons; the one matching the current range as pressed
- Presets outside min/max are announced as unavailable
- After choosing a preset, focus returns to the field and the new range can be read
What your code must do
- Start and end fields are labelled as such
- Choosing a preset announces the new range and returns focus to the field
- Presets outside minValue/maxValue are disabled
Guidelines
Use it when
- Filtering reports or analytics by period
- Booking a stay
Avoid it when
- A single date: use DatePicker
Don't
- Hiding presets on mobile
- Presets that ignore the user's time zone
- Passing isInvalid for required or format checks (even isInvalid={false}): any defined value takes over validity and hides the built-in errors. Use isRequired and validate; pass isInvalid only for errors the app finds itself, such as from the server
Design tokens
The semantic tokens this component uses. Change them once and every component follows; see Design tokens.
--rd-color-surface-default--rd-color-surface-raised--rd-color-surface-subtle--rd-color-border-default--rd-color-border-strong--rd-color-text-default--rd-color-text-muted--rd-color-action-primary--rd-color-feedback-danger--rd-color-focus-ring--rd-radius-control--rd-radius-overlay