Calendar
A date picker calendar component built on react-day-picker. Supports single date selection, date range selection, multiple months, and custom day rendering. Responsive layout switches from vertical to horizontal on wider screens.
Anatomy
<Calendar> renders a full calendar grid with navigation arrows, weekday headers, and day buttons. Uses data-slot="calendar" and provides data attributes for selected, range, today, and outside days.
Selection Modes
The calendar supports single date selection and range selection modes via the mode prop.
Single selection
Range selection
Enhanced Navigation
Use showTodayButtonto add a “Today” button above the grid that snaps the viewed month back to the current date. Use captionLayout="dropdown" with startMonth / endMonth to replace the static caption with month and year dropdowns for faster navigation.
Today button + dropdown navigation
Month & year dropdown only
Design Guidelines
Do
- Use for date selection. Calendar is ideal when users need to pick a specific date or range visually.
- Show outside days. The showOutsideDays prop (on by default) helps users understand the date context.
- Pair with a Popover for inline use. Wrap the calendar in a Popover for space-efficient date pickers.
Don't
- Don't use for known dates. If users are entering a known date (birthday), a text input with date format is faster.
- Don't show too many months. More than 2 side-by-side months creates layout issues on smaller screens.
- Don't forget disabled dates. Use the disabled prop to prevent selection of unavailable dates.
Developer Reference
Accessibility
- Built on react-day-picker — implements WAI-ARIA date picker pattern.
- Arrow keys navigate between days, Page Up/Down for months.
- Day buttons announce their date and selection state to screen readers.
- Today's date is highlighted via
data-today. - Range selection uses
data-range-start,data-range-end,data-range-middle. - Responsive layout: flex-col on mobile, md:flex-row for multi-month.
Usage
import { Calendar } from "@/components/ui/calendar"
// Single date selection
const [date, setDate] = React.useState<Date | undefined>(new Date())
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="rounded-lg border border-border"
/>
// Range selection
const [range, setRange] = React.useState<DateRange | undefined>()
<Calendar
mode="range"
selected={range}
onSelect={setRange}
/>
// With Today button — snaps the viewed month back to today
<Calendar
mode="single"
showTodayButton
className="rounded-lg border border-border"
/>
// Month & year dropdown navigation
<Calendar
mode="single"
captionLayout="dropdown"
startMonth={new Date(new Date().getFullYear() - 10, 0)}
endMonth={new Date(new Date().getFullYear() + 10, 11)}
className="rounded-lg border border-border"
/>
// Combined: Today button + dropdown navigation
<Calendar
mode="single"
showTodayButton
captionLayout="dropdown"
startMonth={new Date(new Date().getFullYear() - 10, 0)}
endMonth={new Date(new Date().getFullYear() + 10, 11)}
className="rounded-lg border border-border"
/>
// With disabled dates
<Calendar
mode="single"
disabled={{ before: new Date() }}
/>
// Multiple months
<Calendar
mode="single"
numberOfMonths={2}
/>