v1.0

Calendar

Date, multi-date and date-range calendar built on React Aria, with month/year chip pickers, presets and a footer.

Pro

August to September 2026

Date range
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11

Description

Calendar wraps React Aria's Calendar and RangeCalendar behind one component. mode picks the selection shape (single, multiple, range) and swaps the underlying React Aria root to match. Rendered bare it's just a month grid; pass children and it becomes a full panel, a presets rail next to a body of month grids and a footer with actions.

Reach for it for date pickers, booking and availability screens, and report date filters. The presets rail (Calendar.Presets) is what makes shortcuts like "Last 7 days" or a fixed time list work without a separate component.

If the user types a date rather than pointing at one, use Input instead of forcing a picker. If the surface is a list of dated records, not a single date choice, that's a Table, not this.

Calendar is a Create UI Pro component. With a Pro seat, npx @create-ui/cli add calendar installs it, and the previews here are marked with a Pro badge. It pulls in Button, Scroll Area and Text Link automatically.

Installation

pnpm dlx @create-ui/cli add calendar

Anatomy

Calendar.Panel is a row of columns: a Calendar.Presets rail, the Calendar.Body (month grids plus footer), and optionally a second Calendar.Presets for a time list.

<Calendar>
  <Calendar.Panel>
    <Calendar.Presets />
    <Calendar.Body>
      <Calendar.Months />
      <Calendar.Footer>
        <Calendar.TodayLink />
        <Calendar.Actions />
      </Calendar.Footer>
    </Calendar.Body>
  </Calendar.Panel>
</Calendar>

Bare <Calendar /> (no children) renders just Calendar.Months. Calendar.Months and Calendar.Month both auto-render their internals (header, grid) when given no children of their own, so most of this tree is optional.

Usage

import { Calendar } from "@/components/ui/calendar"
<Calendar />

Examples

Eight examples, in order: prop-level variations first, selection modes through states, then two full compositions, date range picker with presets and time picker, that show how Calendar.Panel, Calendar.Presets and Calendar.Footer fit together.

Selection modes

mode decides the shape of the controlled value: a single DateValue for "single", an array of them for "multiple", and { start, end } for "range". Switching modes switches the underlying React Aria root, so the controlled value has to switch with it.

Pro

Single

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Range

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Appearances

appearance tints the whole calendar together: selection fill, range rail, today ring, and the Calendar.TodayLink all follow it. primary is indigo, neutral is near-black.

Pro

Primary

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Neutral

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Sizes

size scales the whole shell, not just the day cells: lg is a 40px day with a 24px panel radius and a 72px footer, md is a 32px day with a 16px radius and a 56px footer.

Pro

lg

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

md

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Shapes

shape applies to days, month/year chips and presets at once. rounded follows the responsive component radius, pill goes fully round, square removes it.

Pro

Rounded

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Pill

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Square

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Header variants

headerVariant controls how month and year are navigated. single shows one combined chip, multiple splits month and year into separate chips, plain renders a static heading with no picker at all.

Pro

Single select

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Multiple select

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Plain text

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

States

Pass minValue / maxValue to bound the selectable range, isDateUnavailable to block specific days (weekends, holidays), isDisabled to lock the whole calendar, or outsideMonth="hidden" to blank out days from neighboring months instead of dimming them.

Pro

Min and max value

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Unavailable weekends

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Public holidays

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Disabled

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Outside month hidden

August 2026

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

Date range picker with presets

Calendar.Presets renders a scrollable rail next to Calendar.Body. Each Calendar.Preset with a value writes that range into the calendar and highlights itself while it matches, which is how shortcuts like "Last 7 days" work.

Pro

August to September 2026

Date range
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11

Applied: Aug 29, 2026 – Sep 17, 2026

Time picker

A second Calendar.Presets column works as an ordinary button list instead of a date shortcut: drive isSelected and onPress directly on Calendar.Preset and skip the value prop.

Pro

August to September 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
Pick time

Accessibility

KeyDescription
Arrow Left/Right/Up/DownMoves focus one day at a time
Page Up / Page DownMoves focus to the same day in the previous or next month
Shift + Page Up / Shift + Page DownMoves focus to the same day in the previous or next year
Home / EndMoves focus to the start or end of the current week
Enter / SpaceSelects the focused date
EscapeCancels an in-progress range selection
TabMoves focus to the next focusable part (nav buttons, presets, footer actions)

ARIA notes:

  • The day grid sets role="grid" with each day as a gridcell, via React Aria's CalendarGrid. Only the focused day sits in the native tab order, a roving-tabindex pattern.
  • aria-selected and aria-disabled are managed per cell automatically as selection state changes; the grid's aria-label announces the visible month.
  • Calendar.MonthYearTrigger is a real <button> with aria-expanded and data-state reflecting whether its picker is open.
  • Calendar.TodayLink and Calendar.Preset render as native interactive elements, so pointer and keyboard activation come for free.
  • Built on React Aria's Calendar and RangeCalendar primitives, so announcements for date changes, range start and end, and unavailable dates follow their tested accessibility behavior.

Styling

Tailwind override: pass className to merge Tailwind classes with the component's classes (via cn()):

<Calendar className="gap-6" />

Data slots and attributes:

  • Structure: calendar, calendar-panel, calendar-body, calendar-months, calendar-month, calendar-header, calendar-nav-previous / calendar-nav-next, calendar-month-year, calendar-heading, calendar-month-year-trigger, calendar-month-grid / calendar-year-grid, calendar-month-year-item, calendar-grid, calendar-weekday, calendar-day, calendar-day-range, calendar-day-surface, calendar-day-label, calendar-day-indicator, calendar-presets, calendar-presets-inner, calendar-presets-label, calendar-presets-list, calendar-preset, calendar-footer, calendar-actions, calendar-today-link.
  • State and variant attributes: data-size, data-appearance, data-mode on the root; data-offset and data-view on calendar-month; data-scope and data-state on calendar-month-year-trigger; data-selected on calendar-month-year-item and calendar-preset.
  • React Aria state, mirrored automatically on days and cells: data-selected, data-disabled, data-unavailable, data-outside-month, data-today, data-hovered, data-focus-visible.

calendarDayVariants, calendarMonthYearItemVariants and calendarPresetVariants are exported if you want the class recipes directly.

Target a specific state in CSS:

[data-slot="calendar-day"][data-selected] {
  /* … */
}
  • Popover: pair with Calendar to build a dropdown date picker that opens from a trigger button or input.
  • Input: use when the date should be typed rather than picked from a grid.
  • Table: use for a list of dated records instead of a single date choice.

API Reference

Every part is exported twice: as a member of the Calendar namespace (Calendar.Panel) and as a flat component (CalendarPanel). The headings below use the dotted form.

The date grid, selection, and keyboard behavior come from React Aria Calendar and RangeCalendar. Props marked React Aria are inherited and behave exactly as they do there; everything else is added by Create UI.

Calendar

The selection root. Renders React Aria's Calendar (single, multiple) or RangeCalendar (range) depending on mode, and opens the context every other part reads size, appearance, shape and friends from.

Props

PropTypeDefaultDescription
mode"single" | "multiple" | "range""single"Selection shape. Switches the underlying React Aria root.
sizeCalendarSize"lg"Scales days, panel radius and footer height together.
appearanceCalendarAppearance"primary"Tints selection, range rail, today ring and the Today link together.
shapeCalendarShape"rounded"Radius on days, month/year chips and presets.
headerVariantCalendarHeaderVariant"single"How month and year navigation is presented.
visibleMonthsnumber1Month grids rendered side by side.
visibleYearsnumber12Size of the year chip window in the year picker, centered on the focused year.
fixedWeeksbooleantrueAlways renders six week rows so the grid height never shifts between months.
outsideMonthCalendarOutsideMonth"muted"How days from neighboring months render. React Aria disables them either way.
showTodayIndicatorbooleanfalseDraws a dash under today's cell.
isDateIndicated(date: DateValue) => boolean-Draws a dash under any date this returns true for, independent of showTodayIndicator.
firstDayOfWeek"sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat"locale defaultFirst column of the week grid.
valueDateValue | DateValue[] | RangeValue<DateValue>-React Aria. Controlled selection; shape follows mode.
defaultValuesame as value-React Aria. Uncontrolled initial selection.
onChange(value) => void-React Aria. Fires on selection.
minValueDateValue-React Aria. Earliest selectable date.
maxValueDateValue-React Aria. Latest selectable date.
isDisabledbooleanfalseReact Aria. Disables every cell and nav control.
isReadOnlybooleanfalseReact Aria. Focusable but not selectable.
isDateUnavailable(date: DateValue) => boolean-React Aria. Marks specific dates unselectable, styled as unavailable.
pageBehavior"single" | "visible""single"React Aria. Whether the nav arrows step one month or the whole visible range.
autoFocusboolean-React Aria. Focuses a date on mount.
aria-labelstring-React Aria. Accessible name.
classNamestring-Tailwind classes merged with the component's classes via cn().
childrenReact.ReactNode<Calendar.Months />Panel composition. Defaults to a bare grid of visibleMonths months.

Variants

VariantOptionsDefaultDescription
size"lg" "md""lg"Overall scale.
appearance"primary" "neutral""primary"Color tint.
shape"rounded" "pill" "square""rounded"Corner radius.
mode"single" "multiple" "range""single"Selection shape.
headerVariant"single" "multiple" "plain""single"Month/year navigation style.
outsideMonth"muted" "hidden""muted"How out-of-month days render.

Calendar.Panel

The row shell around a presets rail and the body. Extends React.ComponentProps<"div">. Reads size from context for its border radius; no variants of its own.

Props

PropTypeDefaultDescription
classNamestring-Tailwind classes merged with the component's classes via cn().
childrenReact.ReactNode-A Calendar.Presets rail (or two) and a Calendar.Body.

Calendar.Body

The column holding the month grids and footer, bordered on the left when it follows a presets rail. Extends React.ComponentProps<"div">.

Props

PropTypeDefaultDescription
classNamestring-Tailwind classes merged with the component's classes via cn().
childrenReact.ReactNode-Usually Calendar.Months and Calendar.Footer.

Calendar.Months

The row of month panels. Extends React.ComponentProps<"div">. With no children, renders one Calendar.Month per visibleMonths (read from the root), at consecutive offsets.

Props

PropTypeDefaultDescription
classNamestring-Tailwind classes merged with the component's classes via cn().
childrenReact.ReactNodeone Calendar.Month per visible monthOverrides the auto-generated month panels.

Calendar.Month

One month's panel: header plus grid, or a month/year picker grid when its chip is open. Extends React.ComponentProps<"div">.

Props

PropTypeDefaultDescription
offsetnumber0Which month this panel represents, relative to the visible range. Read by the header, grid and picker beneath it.
classNamestring-Tailwind classes merged with the component's classes via cn().
childrenReact.ReactNodeheader + gridOverrides the auto-generated header and grid.

Calendar.Header

The row above a month's grid: previous/next arrows around the month/year control. Extends React.ComponentProps<"div">.

Props

PropTypeDefaultDescription
offsetnumber0Which month this header belongs to.
classNamestring-Tailwind classes merged with the component's classes via cn().
childrenReact.ReactNodenav buttons + Calendar.MonthYearOverrides the default header layout.

Calendar.Grid

The day grid for one month. Extends React Aria's CalendarGrid props.

Props

PropTypeDefaultDescription
offsetnumber0Which month this grid renders, relative to the visible range.
weekdayStyle"narrow" | "short" | "long""short"React Aria. Format of the weekday header row.
weekdayLengthnumber2Characters shown per weekday header, e.g. 2 for "Mo".
classNamestring-Tailwind classes merged with the component's classes via cn().

Calendar.Day

A single day cell. Extends React Aria's CalendarCell props.

Props

PropTypeDefaultDescription
dateDateValue-React Aria. The date this cell renders. Normally supplied by Calendar.Grid's render function, not set by hand.
classNamestring | (renderProps) => string-Tailwind classes merged with the component's classes via cn(). Also accepts a render function.

Calendar.Presets

A scrollable rail of shortcuts beside Calendar.Body. Extends React.ComponentProps<"div">.

Props

PropTypeDefaultDescription
labelReact.ReactNode-Uppercase heading above the list.
classNamestring-Tailwind classes merged with the component's classes via cn().
childrenReact.ReactNode-Calendar.Preset items.

Calendar.Preset

One shortcut in a Calendar.Presets rail. Extends React Aria's Button props.

Props

PropTypeDefaultDescription
valueCalendarPresetValue-When set, pressing the preset writes this date or range into the calendar; the preset highlights itself while it matches.
isSelectedbooleanauto from valueManual override, needed when the preset isn't driven by a fixed value (e.g. a time slot).
onPress(event: PressEvent) => void-React Aria. Fires on activation, in addition to any value write.
isDisabledbooleanfalseReact Aria. Disables the preset.
classNamestring-Tailwind classes merged with the component's classes via cn().

Calendar.Footer

The bottom bar of a Calendar.Body, sized around its action button. Extends React.ComponentProps<"div">.

Props

PropTypeDefaultDescription
classNamestring-Tailwind classes merged with the component's classes via cn().
childrenReact.ReactNode-Usually Calendar.TodayLink and Calendar.Actions.

Calendar.Actions

Right-aligned button group inside Calendar.Footer. Extends React.ComponentProps<"div">.

Props

PropTypeDefaultDescription
classNamestring-Tailwind classes merged with the component's classes via cn().
childrenReact.ReactNode-Usually Buttons, e.g. Clear and Apply.

A text link that focuses today's date. Extends TextLink props.

Props

PropTypeDefaultDescription
childrenReact.ReactNode"Today"Link label.
onClickReact.MouseEventHandler<HTMLButtonElement>-Fires before the built-in behavior that focuses today's date.

Types

type CalendarMode = "single" | "multiple" | "range"
type CalendarSize = "lg" | "md"
type CalendarAppearance = "primary" | "neutral"
type CalendarShape = "rounded" | "pill" | "square"
type CalendarHeaderVariant = "single" | "multiple" | "plain"
type CalendarOutsideMonth = "muted" | "hidden"
type CalendarPresetValue = DateValue | RangeValue<DateValue>

DateValue and RangeValue come from react-aria-components. Every part also exports its props type (CalendarPanelProps, CalendarPresetProps, and so on).

Composition parts

Pieces the parts above render for you. None needs placing by hand unless you're rebuilding the header yourself.

PartExtendsDescription
Calendar.HeadingReact Aria CalendarHeading props + offset?: numberStatic month/year heading, used directly when headerVariant="plain"; rendered for you otherwise.
Calendar.NavButtonReact Aria Button props + slot: "previous" | "next" (required)Previous/next arrow inside Calendar.Header; steps a year at a time while a month/year picker is open.
Calendar.MonthYearReact.ComponentProps<"div"> + offset?: numberDispatches to Calendar.Heading or one/two Calendar.MonthYearTriggers based on headerVariant.
Calendar.MonthYearTrigger{ offset?: number; scope?: "month" | "year" | "both"; className?: string }The clickable month/year chip that opens Calendar.PickerGrid.
Calendar.PickerGridReact.ComponentProps<"div"> + scope: "month" | "year" (required) + offset?: numberThe 3-column grid of month or year chips shown while a trigger is open.