Date Picker
A date picker component with range and presets.
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
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-labelon 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}
/>Related Components
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.
| Prop | Type | Default | Description |
|---|---|---|---|
| mode | "single" | "multiple" | "range" | "single" | Selection mode passed to the Calendar component. |
| selected | Date | Date[] | DateRange | undefined | undefined | The currently selected date(s). Controlled by parent state. |
| onSelectrequired | (date: Date | undefined) => void | — | Callback 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. |
| disabled | Matcher | Matcher[] | — | Date matcher(s) to disable specific dates (e.g., past dates, weekends). |
| showOutsideDays | boolean | true | Whether to display days from adjacent months in the calendar grid. |
| month | Date | — | Controlled month to display. Use with onMonthChange for synced input + calendar. |
| onMonthChange | (month: Date) => void | — | Callback fired when the displayed month changes via navigation. |