Date & Time/Date Picker

Date Picker

A date picker component with range and presets.

Themed

When to Use

Use Date Picker when you need to:

  • Collect a single date value in a form (e.g., due date, appointment)
  • Allow users to select a date of birth with easy year navigation
  • Combine date and time selection into a single compact control
  • Provide both manual text entry and visual calendar selection
  • Save space in forms where an always-visible calendar is too large

When Not to Use

  • Always-visible date selection (scheduling UIs) - use Calendar directly
  • Displaying events or metadata on dates - use Calendar with custom day rendering
  • Simple known-format date entry - use Input with type="date"
  • Date range filtering in dashboards - consider a dedicated range picker pattern

Default

Basic date picker with a popover trigger. Click the button to open a calendar dropdown.

Date of Birth

Date picker with dropdown navigation for easy month/year selection. The popover closes automatically on date selection.

With Input

Date picker combined with a text input for manual entry. The calendar syncs with typed values and vice versa.

Date and Time

Date picker paired with a native time input for combined date-time selection.

UX & Design Guidelines

Trigger Labeling

Always show the selected date in the trigger button using a human-readable format (e.g., "January 15, 2025"). When no date is selected, use placeholder text like "Pick a date" styled with text-muted-foreground. Include a CalendarIcon to reinforce the control's purpose.

Popover Behavior

Use controlled open state (open / onOpenChange) to auto-close the popover after selection. Align the popover to start for left-aligned triggers or end for right-aligned icon buttons. Use p-0 on PopoverContent to remove default padding around the calendar.

Responsive Behavior

On mobile, the popover calendar uses the full available width. Consider pairing with a text input for manual entry on touch devices where precise tapping can be difficult. The trigger button should be at least 44px tall for adequate touch targets. Use w-full on trigger buttons in narrow form layouts.

Color & Contrast

The trigger button uses variant="outline" to match standard form inputs. Selected dates in the calendar use bg-primary with text-primary-foreground for clear visibility. Today's date is highlighted with bg-accent for easy orientation. Disabled dates use reduced opacity while maintaining readability.

Accessibility

Keyboard Navigation

  • Enter or Space — Open the date picker popover from the trigger
  • Arrow Keys — Navigate between days in the calendar grid
  • Page Up / Page Down — Move to previous/next month
  • Home / End — Jump to start/end of the current week
  • Escape — Close the popover and return focus to the trigger

Screen Reader Support

  • The trigger button announces the selected date or placeholder text
  • Calendar cells announce the full date (e.g., "Thursday, January 15, 2025")
  • Disabled dates are announced as unavailable via aria-disabled
  • Use aria-label on icon-only triggers (e.g., "Select date")

Focus Management

When the popover opens, focus moves to the currently selected date or today's date in the calendar grid. On close, focus returns to the trigger button. The calendar uses focus-visible:ring-[3px] for visible focus indicators that meet WCAG 2.1 Level AA requirements.

Manual Input Alternative

Pair the date picker with a text input for users who prefer typing dates directly. This is especially important for screen reader users and keyboard-only users who may find grid navigation time-consuming. Use aria-describedby to hint that Arrow Down opens the calendar.

ARIA Attributes

{/* Trigger button with descriptive label */}
<Popover>
  <PopoverTrigger asChild>
    <Button variant="outline" aria-label="Choose a date">
      <CalendarIcon className="mr-2 size-4" />
      {date ? format(date, "PPP") : "Pick a date"}
    </Button>
  </PopoverTrigger>
  <PopoverContent>
    <Calendar mode="single" selected={date} onSelect={setDate} />
  </PopoverContent>
</Popover>

{/* With input - connect label for screen readers */}
<Label htmlFor="due-date">Due date</Label>
<Input id="due-date" value={value} aria-describedby="date-help" />
<span id="date-help" className="sr-only">
  Press arrow down to open the calendar picker
</span>

{/* Disabled dates announced via aria-disabled */}
<Calendar
  mode="single"
  disabled={{ before: new Date() }}
  selected={date}
  onSelect={setDate}
/>

API Reference

The Date Picker is a composition of Calendar, Popover, and Button. These are the common Calendar props used when building a date picker.

PropTypeDefaultDescription
mode"single" | "multiple" | "range""single"Selection mode passed to the Calendar component.
selectedDate | Date[] | DateRange | undefinedundefinedThe currently selected date(s). Controlled by parent state.
onSelectrequired(date: Date | undefined) => voidCallback fired when the user selects a date in the calendar.
captionLayout"label" | "dropdown""label"Layout of the month/year navigation. Use "dropdown" for easy year jumping.
disabledMatcher | Matcher[]Date matcher(s) to disable specific dates (e.g., past dates, weekends).
showOutsideDaysbooleantrueWhether to display days from adjacent months in the calendar grid.
monthDateControlled month to display. Use with onMonthChange for synced input + calendar.
onMonthChange(month: Date) => voidCallback fired when the displayed month changes via navigation.