Component reference
DateRangePicker
Pick arrival and departure dates for a reservation.
Preview
Live previewOptional six-digit hex. Clear to restore the preset. Check contrast with your brand color.
Changes apply to this preview only.
Wed, Oct 21 → Sun, Oct 25 · check-in from 3 pm
Width adapts to the available space
"use client";
import { useState } from "react";
import { type PimoluDateRange, DateRangePicker, Badge } from "@pimolu/react";
const TODAY = new Date(2026, 9, 20);
const stayPresets = [
{
label: "This weekend",
range: {
from: new Date(2026, 9, 23),
to: new Date(2026, 9, 25),
},
},
{
label: "Next week",
range: {
from: new Date(2026, 9, 26),
to: new Date(2026, 10, 1),
},
},
];
function dayNumber(date: Date) {
return Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());
}
function countDays(range: PimoluDateRange) {
if(!range.from || !range.to)
return 0;
return (Math.round((dayNumber(range.to) - dayNumber(range.from)) /
86400000) + 1);
}
function formatDate(date: Date | null, locale = "en-US", options: Intl.DateTimeFormatOptions = {
year: "numeric",
month: "long",
day: "numeric",
}) {
if(!date)
return "—";
return new Intl.DateTimeFormat(locale, options).format(date);
}
function BookingExample() {
const [range, setRange] = useState<PimoluDateRange>({
from: new Date(2026, 9, 21),
to: new Date(2026, 9, 25),
});
const nights = countDays(range) - 1;
const complete = Boolean(range.from && range.to);
return (
<div className="grid gap-5 min-w-0">
<DateRangePicker
label="Stay dates"
value={range}
onChange={setRange}
min={TODAY}
max={new Date(2027, 9, 20)}
numberOfMonths={1}
presets={stayPresets}
fullWidth
/>
<div className="flex flex-wrap items-center gap-3 min-w-0 justify-between">
<span className="text-sm text-muted leading-relaxed">Accommodation</span>
<Badge
variant={complete && nights > 0 ? "success" : "neutral"}
appearance="soft"
>
{
complete && nights > 0
? `${nights} ${nights === 1 ? "night" : "nights"}`
: "Choose a stay"
}
</Badge>
</div>
<p className="text-sm text-muted leading-relaxed">
{
complete
? `${formatDate(
range.from,
"en-US",
{
weekday: "short",
month: "short",
day: "numeric",
}
)} → ${formatDate(
range.to,
"en-US",
{
weekday: "short",
month: "short",
day: "numeric",
}
)} · check-in from 3 pm`
: "Pick an arrival and a departure date."
}
</p>
</div>
);
}
export function DemoExample() {
return (<BookingExample />);
}More examples
Different configurations and compositions using the real Pimolu API. Each preview runs independently and follows the site appearance.
Basic
The first click sets the start, the second completes the range and closes the panel. The footer keeps asking for the missing endpoint until then.
Presets
Presets are ordinary data: a label and a range. Choosing a complete preset closes the panel.
Single month
numberOfMonths=1 keeps the panel narrow for mobile or dense forms. The range model is identical.
Usage
Validate ordering and availability in the application; avoid UTC conversions that shift calendar days.
API reference
Generated from the public TypeScript declarations. Native HTML attributes are inherited where the component extends them; this reference includes Pimolu props and selected common native attributes.
PimoluDateRangePreset
Type source| Name | Type | Default | Description |
|---|---|---|---|
labelRequired | string | — | Visible label of the preset button. |
rangeRequired | PimoluDateRange | — | Range applied when the preset is chosen. |
labelRequiredstringNo default extracted.
Visible label of the preset button.
rangeRequiredPimoluDateRangeNo default extracted.
Range applied when the preset is chosen.
PimoluDateRangePickerProps
Type source| Name | Type | Default | Description |
|---|---|---|---|
id | string | undefined | — | Id of the trigger button. Generated when omitted. |
name | string | undefined | — | Name of the hidden start-date input submitted with the form. |
value | PimoluDateRange | undefined | — | Controlled range. Omit to let the picker own it. |
defaultValue | PimoluDateRange | undefined | — | Initial range when uncontrolled. |
onChange | ((range: PimoluDateRange) => void) | undefined | — | Called with the next range, including the empty range when cleared. |
placeholder | string | undefined | "Select date range" | Text shown while no range is selected. Defaults to "Select date range". |
label | string | undefined | — | Visible label, also used as the trigger's accessible name. |
min | Date | undefined | — | Earliest selectable day, inclusive. |
max | Date | undefined | — | Latest selectable day, inclusive. |
disabledDates | PimoluDisabledDates | undefined | — | Dates that cannot be selected, as a list or a predicate. |
presets | readonly PimoluDateRangePreset[] | undefined | — | Shortcuts shown beside the calendars. |
numberOfMonths | 1 | 2 | undefined | 2 | Number of consecutive months. Defaults to 2. |
disabled | boolean | undefined | false | Never open the calendars. |
readOnly | boolean | undefined | false | Keep the value visible and focusable but not editable. |
required | boolean | undefined | false | Marks the field as required and shows the required marker. |
clearable | boolean | undefined | true | Show the clear button when a range is selected. Defaults to true. |
fullWidth | boolean | undefined | false | Stretch the field to the parent width. |
locale | string | undefined | "en-US" | BCP 47 locale for display and calendar labels. Defaults to "en-US". |
weekStartsOn | 0 | 1 | undefined | 0 | First day of the week: 0 = Sunday, 1 = Monday. Defaults to 0. |
clearLabel | string | undefined | — | Accessible label for the clear button. |
className | string | undefined | — | Class applied to the outer field. |
aria-label | string | undefined | — | Accessible name for the trigger when no visible label is used. |
idstring | undefinedNo default extracted.
Id of the trigger button. Generated when omitted.
namestring | undefinedNo default extracted.
Name of the hidden start-date input submitted with the form.
valuePimoluDateRange | undefinedNo default extracted.
Controlled range. Omit to let the picker own it.
defaultValuePimoluDateRange | undefinedNo default extracted.
Initial range when uncontrolled.
onChange((range: PimoluDateRange) => void) | undefinedNo default extracted.
Called with the next range, including the empty range when cleared.
placeholderstring | undefinedDefault: "Select date range"
Text shown while no range is selected. Defaults to "Select date range".
labelstring | undefinedNo default extracted.
Visible label, also used as the trigger's accessible name.
minDate | undefinedNo default extracted.
Earliest selectable day, inclusive.
maxDate | undefinedNo default extracted.
Latest selectable day, inclusive.
disabledDatesPimoluDisabledDates | undefinedNo default extracted.
Dates that cannot be selected, as a list or a predicate.
presetsreadonly PimoluDateRangePreset[] | undefinedNo default extracted.
Shortcuts shown beside the calendars.
numberOfMonths1 | 2 | undefinedDefault: 2
Number of consecutive months. Defaults to 2.
disabledboolean | undefinedDefault: false
Never open the calendars.
readOnlyboolean | undefinedDefault: false
Keep the value visible and focusable but not editable.
requiredboolean | undefinedDefault: false
Marks the field as required and shows the required marker.
clearableboolean | undefinedDefault: true
Show the clear button when a range is selected. Defaults to true.
fullWidthboolean | undefinedDefault: false
Stretch the field to the parent width.
localestring | undefinedDefault: "en-US"
BCP 47 locale for display and calendar labels. Defaults to "en-US".
weekStartsOn0 | 1 | undefinedDefault: 0
First day of the week: 0 = Sunday, 1 = Monday. Defaults to 0.
clearLabelstring | undefinedNo default extracted.
Accessible label for the clear button.
classNamestring | undefinedNo default extracted.
Class applied to the outer field.
aria-labelstring | undefinedNo default extracted.
Accessible name for the trigger when no visible label is used.
Accessibility
- Label the range, make both endpoints understandable and verify clear/open/close focus behavior.