Date Range Picker

Picks a start and end date from a calendar.

Installation

pnpm dlx shadcn@latest add @paneui/date-range-picker

Usage

Composition

Examples

Inline

Leave out the trigger and content when the calendar should sit in the page instead of a popup.

Unavailable Dates

Locale

Controlled

Keyboard

Each month is a grid with one tab stop. Arrows move by day and week, Home/End to the week's edges, PageUp/PageDown by month (with Shift, by year). Enter or Space picks the start, then the end; while choosing the end the range previews.

Motion

With reduced motion, month changes cross-fade instead of sliding.

API Reference

Built on the Popover primitive. Only the props this library adds or changes are listed; everything else passes through.

DateRangePicker

Range state plus the popover root. Dates are local-midnight Dates. Also accepts every prop of Popover.Root.

value
{ from?: Date; to?: Date }
Controlled range.
defaultValue= {}
{ from?: Date; to?: Date }
Initial range when uncontrolled.
onValueChange
(range: DateRange) => void
Called on every pick, clear or preset.
locale= the browser's
string
BCP 47 locale for names and formatting.
weekStartsOn= the locale's
number
First column: 0 Sunday … 6 Saturday.
numberOfMonths= 1
1 | 2
Months shown side by side.
min
Date
Earliest selectable day.
max
Date
Latest selectable day.
isDateDisabled
(date: Date) => boolean
Extra rule for unavailable days.
closeOnComplete= false
boolean
Close the popover once both ends are picked.
PropTypeDefaultDescription
value{ from?: Date; to?: Date }—Controlled range.
defaultValue{ from?: Date; to?: Date }{}Initial range when uncontrolled.
onValueChange(range: DateRange) => void—Called on every pick, clear or preset.
localestringthe browser'sBCP 47 locale for names and formatting.
weekStartsOnnumberthe locale'sFirst column: 0 Sunday … 6 Saturday.
numberOfMonths1 | 21Months shown side by side.
minDate—Earliest selectable day.
maxDate—Latest selectable day.
isDateDisabled(date: Date) => boolean—Extra rule for unavailable days.
closeOnCompletebooleanfalseClose the popover once both ends are picked.

DateRangePickerTrigger

Button that shows the formatted range (Intl.formatRange). Also accepts every prop of Popover.Trigger.

placeholder= "Pick dates"
string
Shown while nothing is selected.
formatOptions= { month: "short", day: "numeric", year: "numeric" }
Intl.DateTimeFormatOptions
How the range is formatted.
PropTypeDefaultDescription
placeholderstring"Pick dates"Shown while nothing is selected.
formatOptionsIntl.DateTimeFormatOptions{ month: "short", day: "numeric", year: "numeric" }How the range is formatted.
data-placeholder
Present while showing the placeholder.
Data attributeDescription
data-placeholderPresent while showing the placeholder.

DateRangePickerContent

The library PopoverContent with tighter padding and auto width. Also accepts every prop of PopoverContent.

align= "start"
"start" | "center" | "end"
Trigger edge the panel lines up with.
PropTypeDefaultDescription
align"start" | "center" | "end""start"Trigger edge the panel lines up with.

DateRangePickerCalendar

Month titles, previous/next buttons and one grid per visible month. Also accepts every prop of div.

DateRangePickerGrid

One month's day grid with roving focus. Used by the calendar; render it yourself for custom layouts. Also accepts every prop of div.

month*
Date
Any day in the month to show.
hideOutsideDays= false
boolean
Leave days of neighbouring months blank.
PropTypeDefaultDescription
month*Date—Any day in the month to show.
hideOutsideDaysbooleanfalseLeave days of neighbouring months blank.
data-selected
On a day button that is the start or end.
data-in-range
On days between start and end.
data-preview-end
On the hovered or focused end while choosing.
data-outside
On days from a neighbouring month.
Data attributeDescription
data-selectedOn a day button that is the start or end.
data-in-rangeOn days between start and end.
data-preview-endOn the hovered or focused end while choosing.
data-outsideOn days from a neighbouring month.

DateRangePickerSummary

The range and its length ("Mar 3 – 9 · 6 nights"), or a prompt for the next pick, announced in a polite live region. Also accepts every prop of p.

unit= ["night", "nights"]
[string, string] | null
Singular and plural for the length; null hides it.
formatOptions= { month: "short", day: "numeric" }
Intl.DateTimeFormatOptions
How the range is formatted.
PropTypeDefaultDescription
unit[string, string] | null["night", "nights"]Singular and plural for the length; null hides it.
formatOptionsIntl.DateTimeFormatOptions{ month: "short", day: "numeric" }How the range is formatted.

DateRangePickerFooter

Row under the calendar, separated by a hairline. Also accepts every prop of div.

DateRangePickerClear

Clears the range. Disabled while nothing is selected. Also accepts every prop of button.

children= "Clear"
ReactNode
Button label.
PropTypeDefaultDescription
childrenReactNode"Clear"Button label.

DateRangePickerPresets

Vertical group of presets, labelled Presets. Also accepts every prop of div.

DateRangePickerPreset

Quick range button; aria-pressed when it matches the selection. Also accepts every prop of button.

range*
DateRange | (() => DateRange)
The range to apply. A function is evaluated at click time, e.g. for "Last 7 days".
PropTypeDefaultDescription
range*DateRange | (() => DateRange)—The range to apply. A function is evaluated at click time, e.g. for "Last 7 days".

useDateRangePicker

Picker state and actions for custom parts. Use inside DateRangePicker.

range
DateRange
Current range.
setRange
(next: DateRange) => void
Replace the range.
selectDate
(date: Date) => void
Pick a day as if clicked.
clear
() => void
Clear the range.
month
Date
First visible month.
setMonth
(month: Date) => void
Page to a month.
isDisabled
(date: Date) => boolean
Whether a day is unavailable.
close
() => void
Close the popover (no-op inline).
PropTypeDefaultDescription
rangeDateRange—Current range.
setRange(next: DateRange) => void—Replace the range.
selectDate(date: Date) => void—Pick a day as if clicked.
clear() => void—Clear the range.
monthDate—First visible month.
setMonth(month: Date) => void—Page to a month.
isDisabled(date: Date) => boolean—Whether a day is unavailable.
close() => void—Close the popover (no-op inline).