Skip to content

ComponentsDate & Time

Date Picker

A segmented date field with a calendar popover, for single dates, dates with a time, or date ranges. Users can type or pick; both stay in sync, with min/max bounds, unavailable dates, validation and native form submission built in.

React AriaSource
Due date

Installation

pnpm dlx shadcn@latest add @desyne/date-picker

The CLI installs dependencies and any other components this one uses.

Usage

tsx
import { DatePicker, DateRangePicker } from "@/components/ui/date-picker";
tsx
<DatePicker label="Due date" />
<DateRangePicker label="Trip dates" />

Values are @internationalized/date objects

value is a CalendarDate (or CalendarDateTime / ZonedDateTime when you need a time), and ranges are { start, end }. Create values with today(), parseDate() or parseZonedDateTime() from @internationalized/date, and store them with value.toString().

When to use

  • Date Picker — the default for dates in forms. Typing is fast for known dates; the calendar helps with relative ones ("the second Friday").
  • Date Range Picker — a start and end date in one field: bookings, reports, leave requests.
  • Date Field — typed entry only, for dates far from today (birthdays) where a calendar would need many clicks.
  • Calendar — an always-visible grid, when there's room on the page.

Anatomy

tsx
<DatePicker>                 {/* or <DateRangePicker> */}
  <Label />
  <FieldGroup>               {/* field chrome */}
    <DateInput />            {/* segments; start + end for ranges */}
    <Button />               {/* opens the calendar */}
  </FieldGroup>
  <Description />
  <FieldError />
  <Popover>
    <Dialog>
      <Calendar />           {/* or <RangeCalendar> */}
    </Dialog>
  </Popover>
</DatePicker>
PartRendersNotes
DatePicker<div>Root. data-slot="date-picker".
DateRangePicker<div>Root for ranges. data-slot="date-range-picker".
Group<div role="group">FieldGroup with the shared variant / size styles. Highlights while the popover is open.
Date input<div>Segmented input, styled with dateSegmentStyles. Ranges render a start and end input with an arrow between.
Trigger<button>Ghost icon Button with a calendar icon.
Label / Description / FieldError<span>Rendered from label, description and validation.
PopoverPopover › DialogPlaced bottom start, flips when there's no room.
CalendarCalendar / RangeCalendarThe same Calendar. Inherits minValue, maxValue, isDateUnavailable, firstDayOfWeek and pageBehavior from the picker.

Examples

Controlled

value and onChange own the value; set it to null to clear.

Renewal date

Renews Monday, October 19, 2026

Range

DateRangePicker edits a { start, end } range with two segmented inputs and a RangeCalendar. Picking in the calendar sets both at once.

Trip dates

Variants

Outline
Filled
Underlined

Sizes

Small
Medium
Large

Min and max

Dates outside minValue / maxValue are disabled in the calendar, and typed values outside them are flagged invalid with a localized message. Here validationBehavior="aria" shows the error straight away; with the default native behavior it appears after the value changes or the form is submitted.

Start date
Within the next three months.Value must be 10/5/2026 or later.

Month and year dropdowns

captionLayout, fromYear and toYear are passed to the calendar in the popover (see Calendar). Use captionLayout="dropdown" for dates years away from today, like a date of birth, so nobody has to click back month by month. placeholderValue sets the month the calendar opens on.

Date of birth
Pick a month and year from the calendar header.

The range picker takes the same props. Here the year list is limited to this year and next by minValue and maxValue.

Check-in and check-out
Reservations open up to a year ahead.

Unavailable dates

isDateUnavailable strikes dates through in the calendar and marks a typed unavailable date invalid.

Pickup date
Weekdays only, excluding public holidays.

Date and time

With granularity="minute" (or hour / second) the field adds time segments. The calendar picks the date and keeps the time. Use a ZonedDateTime for a specific time zone, hideTimeZone to hide its abbreviation, and hourCycle to force a 12- or 24-hour clock.

Reminder
Maintenance window (UTC)

Range validation

validate receives the whole range. Combine it with isRequired and minValue; with validationBehavior="aria" on the form, errors update live.

Vacation
Up to 14 days per request.Requests are limited to 14 days. Split longer leave into two requests.

Form submission

name submits a DatePicker value as an ISO 8601 string. DateRangePicker submits two fields, named with startName and endName.

Publish on
Promotion

Locales and first day of the week

Format, segment order and the calendar's first weekday follow the locale. Wrap pickers in I18nProvider to set one, or override the week start with firstDayOfWeek.

English (UK)
German
Week starts on Monday

Disabled and read-only

isDisabled disables the segments and the trigger. isReadOnly keeps the value focusable and readable, but the calendar can't open.

Signed on
Effective from

Controlled open state

isOpen and onOpenChange control the popover, for example to open it from another button. shouldCloseOnSelect={false} keeps it open after a date is picked.

Follow-up
Stays open after picking. Press Esc or click outside to close.

Recipes

Report period with presets

A preset Select next to a DateRangePicker. Choosing a preset fills the range; editing the range switches the preset to "Custom". maxValue blocks future dates.

Period

A native <form> with a required range (sold-out nights unavailable, the night count in the description), startName / endName for submission, and a NumberField for guests.

Find a room

Check-in → check-out
Sold-out nights are struck through.

Quick picks

Shortcut buttons under the field for common due dates. They set the same controlled value the picker uses, and the active one is highlighted.

Due date

Accessibility

  • The field is a role="group" labelled by label. Segments are spin buttons, exactly like Date Field.
  • The trigger button is labelled "Calendar" together with the field label, and is disabled when the picker is disabled or read-only.
  • The popover is a dialog. Focus moves into the calendar when it opens (to the selected date, or today) and returns to the field when it closes.
  • Everything outside the popover is hidden from screen readers while it's open.
  • description and the error message are linked with aria-describedby; invalid pickers set aria-invalid.
  • Always provide a label: label, aria-label, or aria-labelledby.

Keyboard

KeyAction
Alt+↓ / Alt+↑Opens the calendar from the field
Space / EnterOpens the calendar from the trigger button
← / → / ↑ / ↓In the field: moves between / steps segments. In the calendar: moves between days
Page Up / Page DownIn the calendar: previous / next month
Enter / SpaceIn the calendar: selects the focused date and closes
EscCloses the calendar and returns focus to the field

See Calendar and Date Field for the full lists.

Styling

Data attributes

On the DatePicker / DateRangePicker root (use group-data-*/field: for children):

AttributePresent when
data-openThe calendar popover is open (the group border uses it)
data-focus-within / data-focus-visibleSomething inside has focus / keyboard focus
data-invalidValidation failed or isInvalid is set
data-disabledisDisabled is true
data-readonlyisReadOnly is true
data-requiredisRequired is true

On the field group:

AttributePresent when
data-hoveredHovered with a mouse
data-focus-within / data-focus-visibleA segment or the trigger has focus / keyboard focus
data-invalid / data-disabledMirrors the picker

Segments expose the same attributes as in Date Field, and calendar cells as in Calendar.

Slots

data-slotElement
date-picker / date-range-pickerRoot
field-groupField chrome
buttonCalendar trigger
label, description, field-errorField text
popoverCalendar popover
calendar / range-calendarCalendar inside the popover

Customizing

  • className sizes and positions the whole picker (e.g. w-full max-w-60). It also accepts a function of the render props.
  • The field chrome uses the shared fieldVariants, so pickers line up with text fields and selects of the same size.
  • Segments use the exported dateSegmentStyles from Date Field.
  • The popover and calendar are fixed parts. For a different popover layout (presets beside the calendar, two months), compose React Aria's DatePicker with this library's Popover and Calendar.

API Reference

DatePicker

Prop

Type

Also accepts every prop of React Aria's DatePicker.

DateRangePicker

Accepts the same props as DatePicker, with range values:

Prop

Type

Also accepts every prop of React Aria's DateRangePicker.

  • Calendar — the calendar on its own, including multiple months and multi-date selection.
  • Date Field — typed dates and times, and TimeField.
  • Popover — for building custom picker layouts.
  • Select — pairs well with range pickers for presets.