Calendar
Accessible date and range selection with React DayPicker and Migoy styling.
Preview
November 12, 2026
Installation
pnpm dlx shadcn@latest add http://127.0.0.1:3017/r/calendar.jsonInstalls Calendar, Migoy Button, React DayPicker, date-fns, and Lucide icons. Uses your existing theme and cn utility. The endpoint is local; see the registry guide for reviewed updates.
The linked shadcn Base UI Calendar is built on React DayPicker. It uses DayPicker's selection API, with no Base UI trigger composition required.
Usage
'use client';
import * as React from 'react';
import { Calendar } from '@/components/ui/calendar';
export function DateSelection() {
const [date, setDate] = React.useState<Date | undefined>();
return (
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="rounded-lg border"
aria-label="Choose a date"
/>
);
}Use required to prevent clearing the selection. Use mode="multiple" with a Date[] selection to choose independent dates. Selection is controlled through selected and onSelect; omitting a selection mode displays a calendar without selectable dates.
Composition
Calendar wraps React DayPicker and assembles its navigation, month grids, and day buttons internally:
Calendar
├── Month navigation (internal)
└── Month grid (one per displayed month, internal)
└── CalendarDayButton (one per selectable day, internal)Render Calendar directly; do not manually nest day buttons inside it. Configure selection with mode, selected, and onSelect. Use the components, classNames, and formatters props for supported customization. CalendarDayButton is exported for custom DayPicker day-button implementations, where DayPicker supplies its day and modifiers props.
To anchor a calendar to a button, use the Date Picker composition with Popover.
Date range
November 12, 2026 – November 17, 2026
import type { DateRange } from 'react-day-picker';
const [range, setRange] = React.useState<DateRange | undefined>();
<Calendar
mode="range"
selected={range}
onSelect={setRange}
numberOfMonths={2}
className="rounded-lg border"
/>Months stack on narrow screens. min and max constrain the number of nights. Use excludeDisabled with disabled dates when ranges must not cross unavailable days.
Dropdown navigation and disabled dates
Choose a weekday; weekends are unavailable.
<Calendar
mode="single"
captionLayout="dropdown"
startMonth={new Date(2026, 0)}
endMonth={new Date(2027, 11)}
disabled={{ dayOfWeek: [0, 6] }}
selected={date}
onSelect={setDate}
/>Set explicit navigation bounds for dropdowns. Disabled dates remain visible but cannot be selected. Navigation bounds and selectable-date bounds are separate: use disabled to restrict selection as well.
Customization
| Prop | Default / purpose |
|---|---|
showOutsideDays | true |
captionLayout | label; supports dropdown layouts |
buttonVariant | ghost navigation buttons |
locale | DayPicker locale, including translated labels |
weekStartsOn | Locale default; 1 for Monday |
showWeekNumber | Optional week-number column |
classNames, components, formatters | Override DayPicker slots |
timeZone | Explicit IANA zone when required |
CalendarDayButton is also exported for custom day content. Day cells use the shared 32px control height and 4px radius fallbacks. For a larger touch layout, set className="[--cell-size:44px]". Selected dates use primary tokens, ranges use muted tokens, and today has a neutral highlight. The component adds no default shadow.
Demo calendars use November 2026 and a fixed today marker for reproducible previews. Product calendars use the actual current date unless today is supplied. Construct date-only values with new Date(year, monthIndex, day) to avoid parsing UTC date strings into the previous local day. For explicit timeZone usage, use timezone-aware date values consistently as described by DayPicker.
Accessibility
- Tab enters the calendar; arrow keys move between days.
- Enter or Space selects the focused date. Page Up and Page Down navigate months.
- Selected, disabled, and today states retain DayPicker's accessible labels.
- Give the calendar a clear accessible name and show the selected date in accompanying text.
- When placing a calendar inside a Popover, provide a popover title and manage dismissal after selection.
Based on shadcn Calendar and React DayPicker.