Skip to content

Now in the official shadcn registry directory.

Start free

Calendar

A date calendar on react-day-picker v10, styled with the ai2 Button and tokens. Single, multiple and range selection, label or dropdown caption.

form
A free styled version is available
January 2026

Installation

Run the following command

npx shadcn@latest add @ai2/calendar

react-day-picker, the ai2 Button, the @ai2/tokens theme and the component file are installed together.

Usage

TS
import { Calendar } from "@/components/ui/calendar"

<Calendar mode="single" className="rounded-xl border border-border" />

Hold the selection in React state and pass it back through selected and onSelect. The base component is frameless, so add a border and rounding through className.

Examples

Single day

August 2026

Date range

August 2026
September 2026

Set mode="range" and hold a DateRange state. The start, middle and end days each get their own token-driven highlight.

August 2026

captionLayout="dropdown" turns the month and year caption into select menus. Pair it with startMonth and endMonth to bound the range.

Hide outside days

August 2026

showOutsideDays={false} drops the leading and trailing days of adjacent months, leaving a strictly single-month grid.

Localized

julio 2026

Pass any date-fns locale from react-day-picker/locale to translate the weekday and month names and set the first day of the week. This example uses Spanish (es).

Props

Calendar forwards every react-day-picker DayPicker prop. The most common ones are listed here.

PropTypeDefaultDescription
mode"single" | "multiple" | "range"undefinedSelection behaviour: a single day, several individual days, or a continuous range. Determines the shape of selected and the onSelect argument.
selectedDate | Date[] | DateRangeundefinedThe controlled selection, typed to match mode: a Date for single, a Date array for multiple, and a { from, to } DateRange for range.
onSelect(value) => voidundefinedFires when the user picks a day. The argument matches mode, so pass a state setter of the corresponding type.
captionLayout"label" | "dropdown" | "dropdown-months" | "dropdown-years""label"How the month and year caption renders: a static label, or select dropdowns for fast navigation.
showOutsideDaysbooleantrueShow the trailing and leading days of adjacent months to fill the first and last week of the grid.
numberOfMonthsnumber1How many months to render side by side, useful with range selection.
buttonVariant"solid" | "soft" | "outline" | "ghost" | "link""ghost"The ai2 Button variant used for the previous and next navigation buttons.
startMonth / endMonthDateundefinedBound the navigable range and populate the dropdown caption with the corresponding months and years.
localeLocaleenUSA date-fns locale from react-day-picker/locale. Localizes weekday and month names, the dropdown caption and the first day of the week.
classNamestringundefinedClasses for the calendar root. Add border and radius here, since the base component ships without a frame.

ai2 Calendar: a react-day-picker date grid for React

The ai2 Calendar is a shadcn-compatible date calendar for React, built on react-day-picker v10 and styled with the ai2 Button and Tailwind CSS v4 tokens. It renders an accessible month grid with keyboard navigation and supports single day, multiple day and continuous range selection through one mode prop.

Because it ships through the shadcn registry format, you install it with one CLI command, an MCP agent, or a copy-paste, and the source lands in your own project. You own the file; there is no runtime dependency on ai2 itself. The live example above is the exact component you get.

What is the ai2 Calendar?

It is a thin, well-styled wrapper around the react-day-picker DayPicker component. Every day cell is an ai2 Button, the navigation chevrons come from lucide-react, and the month grid, weekday row and caption read from the shared ai2 token file, so the calendar matches the rest of your UI in both light and dark mode.

It exports two parts: Calendar and CalendarDayButton. All react-day-picker props pass straight through, so mode, selected, onSelect, captionLayout, showOutsideDays, numberOfMonths, disabled dates and the rest of the DayPicker API keep working exactly as documented upstream.

Why use it

  • Three selection modes: One mode prop switches between single, multiple and range selection, with selected and onSelect typed to match each case.
  • Keyboard and screen reader ready: react-day-picker handles arrow-key navigation, focus management and ARIA roles, so the grid is usable without a mouse out of the box.
  • Label or dropdown caption: captionLayout switches the month and year caption between a static label and select dropdowns for jumping across months and years quickly.
  • Token-driven styling: Selected, range, today and outside days all read from the ai2 token file, so the calendar stays consistent in light and dark mode with no extra CSS.
  • Agent-readable metadata: The registry item describes its modes and parts in plain words, so an MCP agent can find, inspect and install it without guessing.

Features

  • shadcn registry install: One command adds the component, react-day-picker, the ai2 Button dependency and the @ai2/tokens theme to your project.
  • ai2 Button day cells: CalendarDayButton renders each day with the ghost Button variant, so hover, focus ring and selected states match your buttons.
  • Range highlighting: Range mode marks the start, middle and end days with distinct token-driven backgrounds via data-range-start, data-range-middle and data-range-end.
  • Configurable navigation: buttonVariant sets the previous and next button style, and startMonth with endMonth bound the navigable window and fill the dropdown caption.
  • Outside days toggle: showOutsideDays fills the first and last week with adjacent-month days, or hides them for a strictly single-month grid.
  • Data attributes for styling: Every part exposes data-slot, and day cells expose selection and range data attributes, so you can restyle states from CSS without forking the component.

Production tips

  • Match the selected type to mode: Use a Date for single, a Date array for multiple and a { from, to } DateRange for range. Passing the wrong shape stops selection from rendering.
  • Add your own frame: The base Calendar ships without a border. Add border and rounding through className, or drop it inside a Card or Popover which already provide the frame.
  • Use dropdown caption for wide ranges: When users pick birthdays or historical dates, captionLayout="dropdown" with startMonth and endMonth beats clicking the chevron dozens of times.
  • Disable dates with the matcher API: Pass the react-day-picker disabled prop, for example { before: new Date() }, to block past days rather than filtering selections after the fact.
  • Show two months for ranges: numberOfMonths={2} makes range selection far easier, since users can see both ends of the range without paging between months.

Works with the rest of ai2

The Calendar is the grid behind the ai2 Date Picker, which drops it into a Popover for a compact date field. Each day cell is an ai2 Button, so hover and focus states match the rest of your controls.

Place a Calendar inside a ai2 Card for a framed scheduling panel, or inside a ai2 Popover to build your own trigger. Everything shares one token source, so combinations stay visually consistent in both modes.

FAQs

Get new components in your inbox

Component drops, new themes and release notes. No spam, and you can unsubscribe from any email.

© 2026 ai2 design system · MIT licensed · Built with its own components