Calendar
Month grid for due dates. react-day-picker v9, Phosphor carets.
Calendar is a month grid on the page for picking a day, a range, or several days. It is
react-day-picker v9 drawn with the kit's ghost buttons and Phosphor carets, the chosen day
fills with bg-primary, and today takes the bg-fill wash. To open it from a field and
close it on the pick, use Date picker.
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Usage
'use client';
import * as React from 'react';
import { Calendar } from '@/components/ui/calendar';
export function DueDate() {
const [date, setDate] = React.useState<Date | undefined>();
return <Calendar mode="single" selected={date} onSelect={setDate} />;
}The file exports Calendar and CalendarDayButton. Its onSelect is a function, so render
it from a client component, as above. It paints its own bg-surface with 12px of padding,
and inside a Popover it drops the fill and takes the
popover's surface. On another surface, like a Card, pass className="bg-transparent" to do
the same. Month and day names are in English unless you pass a locale from
react-day-picker/locale.
Picking a day, a range, or several
mode sets what a click picks. "single" picks one day, and clicking the chosen day again
clears it unless required is set. "multiple" adds or removes each day you click, and
"range" picks a { from, to } range whose ends fill with bg-primary and whose days in
between take a bg-fill band. Without a mode the days are plain text and nothing can be
picked.
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
numberOfMonths shows more than one month. They sit side by side from the md breakpoint
up and stack below it. Days from the months before and after fill out the first and last
weeks in muted text, which showOutsideDays={false} turns off.
Limiting the days
disabled takes react-day-picker matchers, like { before: new Date() } for past days or
{ dayOfWeek: [0, 6] } for weekends. The days it matches drop to 64% opacity, cannot be
picked, and are skipped by the arrow keys. startMonth and endMonth stop the month arrows
at a bound, and an arrow with nowhere to go dims and leaves the tab order. Below, past days
and weekends are off, and the calendar cannot go back before this month.
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Month and year menus
captionLayout="dropdown" swaps the caption for a month menu and a year menu, so a date
years away is two picks rather than a long run of clicks. "dropdown-months" and
"dropdown-years" show one of the two. Each menu is a native <select> under the caption's
text, and the years run from 100 years back to the end of this year unless you set
startMonth and endMonth. The month menu uses short month names in the calendar's
locale, so the server and the browser render the same names.
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Props
Calendar takes every react-day-picker DayPicker prop, and adds or changes these.
| Prop | Type | Default | What it does |
|---|---|---|---|
buttonVariant | "default" | "secondary" | "outline" | "ghost" | "destructive" | "link" | "ghost" | The variant of the previous and next month buttons. Days stay ghost. |
showOutsideDays | boolean | true | Shows the days of the months around this one in muted text. react-day-picker defaults it to false. |
classNames, components, and formatters are spread over the kit's, so a key you pass
replaces the kit's for that part and the rest stay as they are. CalendarDayButton is the kit's day, exported so a
DayButton of your own can wrap it. The rest are react-day-picker's, like mode,
selected, onSelect, required, disabled, startMonth, endMonth, numberOfMonths,
weekStartsOn, locale, footer, and autoFocus, and
its docs cover them.
Accessibility
- Each month is a
gridnamed by its month and year, with each weekday header named in full, like "Sunday", and each day agridcell. A day reads as its full date, with "Today" before it and "selected" after it when they apply, like "Today, Thursday, October 1st, 2026, selected". - Only one day is in the tab order: the day you last focused, or else the chosen day, or else today, or else the first day that can be picked. Tab reaches the month buttons first and then that day.
- On a day, ← and → move a day, ↑ and ↓ move a week, and Home and End go to the start and end
of the week. PageUp and PageDown move a month, or a year with Shift, and Shift with ← and →
moves a month and with ↑ and ↓ a year. When focus moves into another month, the calendar
turns to it. Enter or Space picks the focused day. With
dir="rtl"the grid and the month buttons mirror, their arrows point the reading way, and ← and → swap. - The month caption is a polite live region, so a screen reader hears the new month when it
changes. A
footeris one too, for a line like "You picked October 1". - The month buttons are named "Go to the Previous Month" and "Go to the Next Month". At a
startMonthorendMonthbound the button isaria-disabledand leaves the tab order. - A disabled day is a disabled button, and the arrow keys skip it.
mode="multiple"andmode="range"mark the gridaria-multiselectable. - The focused day shows a 2px ring, and in forced colors it keeps an outline that the system paints.
- The chosen day, a range, and today are marked only by fills, which forced colors repaints, so in Windows high contrast they look like any other day and only their names say which they are.
- On a touch screen each day grows to 44px square and the month buttons to 44px tall, so the calendar takes more room.
- The grid does not animate when the month changes, and under reduced motion the days change color on hover without a transition.
When to use something else
- Date picker for a date field in a form. It opens this calendar in a Popover from a button that shows the date, and closes it on the pick. It picks one day, so for a range or several days behind a button, put a Calendar in a Popover yourself, as the Date picker page shows.
Install
shadcn add @gesso/calendarIt brings Button for the days and the month buttons, and installs react-day-picker and date-fns.