27.7k

Calendar

Composable date picker with month grid, navigation, and year picker support built on React Aria Calendar

Import

import { Calendar } from '@darkcode-ui/react';

Usage

"use client";

import {Calendar} from "@darkcode-ui/react";

export function Basic() {

Anatomy

import {Calendar} from '@darkcode-ui/react';

export default () => (
  <Calendar aria-label="Event date">
    <Calendar.Header>
      <Calendar.Heading />
      <Calendar.NavButton slot="previous" />
      <Calendar.NavButton slot="next" />
    </Calendar.Header>
    <Calendar.Grid>
      <Calendar.GridHeader>
        {(day) => <Calendar.HeaderCell>{day}</Calendar.HeaderCell>}
      </Calendar.GridHeader>
      <Calendar.GridBody>
        {(date) => <Calendar.Cell date={date} />}
      </Calendar.GridBody>
    </Calendar.Grid>
  </Calendar>
)

Year Picker

Calendar.YearPickerTrigger, Calendar.YearPickerGrid, and their body/cell subcomponents provide an integrated year navigation pattern.

"use client";

import {Calendar} from "@darkcode-ui/react";

export function YearPicker() {

Default Value

"use client";

import {Calendar} from "@darkcode-ui/react";
import {parseDate} from "@internationalized/date";

Controlled

Use controlled value and focusedValue for external state coordination and custom shortcuts.

"use client";

import type {DateValue} from "@internationalized/date";

import {Button, ButtonGroup, Calendar, Description} from "@darkcode-ui/react";

Multiple Selection

Set selectionMode="multiple" to let users select several dates at once. In this mode value, defaultValue, and onChange work with an array of dates (DateValue[]) instead of a single date.

"use client";

import type {DateValue} from "@internationalized/date";

import {Calendar, Description} from "@darkcode-ui/react";

Min and Max Dates

"use client";

import {Calendar, Description} from "@darkcode-ui/react";
import {getLocalTimeZone, today} from "@internationalized/date";

Unavailable Dates

Use isDateUnavailable to block dates such as weekends, holidays, or booked slots.

"use client";

import type {DateValue} from "@internationalized/date";

import {Calendar, Description} from "@darkcode-ui/react";

Disabled

"use client";

import {Calendar, Description} from "@darkcode-ui/react";
import {getLocalTimeZone, today} from "@internationalized/date";

Read Only

"use client";

import {Calendar, Description} from "@darkcode-ui/react";
import {getLocalTimeZone, today} from "@internationalized/date";

Focused Value

Programmatically control which date is focused using focusedValue and onFocusChange.

"use client";

import type {DateValue} from "@internationalized/date";

import {Button, Calendar, Description} from "@darkcode-ui/react";

Cell Indicators

You can customize Calendar.Cell children and use Calendar.CellIndicator to display metadata like events.

"use client";

import {Calendar} from "@darkcode-ui/react";
import {getLocalTimeZone, isToday} from "@internationalized/date";

Multiple Months

Render multiple grids with visibleDuration and offset for booking and planning experiences.

"use client";

import {Calendar} from "@darkcode-ui/react";
import {getLocalTimeZone} from "@internationalized/date";
import React from "react";

Week View

Show a fixed number of weeks by passing visibleDuration={{weeks: n}}. The grid keeps its seven columns and renders the requested number of rows.

"use client";

import {Calendar} from "@darkcode-ui/react";

export function WeekView() {

Day View

Show a horizontal strip of days by passing visibleDuration={{days: n}}. The column count follows the visible day span (capped at seven so week-or-longer ranges stay week-aligned).

"use client";

import {Calendar} from "@darkcode-ui/react";

export function DayView() {

International Calendars

By default, Calendar displays dates using the calendar system for the user's locale. You can override this by wrapping your Calendar with I18nProvider and setting the Unicode calendar locale extension.

The example below shows the Indian calendar system:

"use client";

import {Calendar} from "@darkcode-ui/react";
import {getLocalTimeZone, today} from "@internationalized/date";
import {I18nProvider} from "react-aria-components";

Note: The onChange event always returns a date in the same calendar system as the value or defaultValue (Gregorian if no value is provided), regardless of the displayed locale. This ensures your application logic works consistently with a single calendar system while still displaying dates in the user's preferred format.

Custom Navigation Icons

Pass children to Calendar.NavButton to replace the default chevron icons.

"use client";

import {Calendar} from "@darkcode-ui/react";

export function CustomIcons() {

Real-World Example

"use client";

import type {DateValue} from "@internationalized/date";

import {Button, Calendar} from "@darkcode-ui/react";

Custom Styles

"use client";

import {Calendar} from "@darkcode-ui/react";

export function CustomStyles() {

Styling

Passing Tailwind CSS classes

import {Calendar} from '@darkcode-ui/react';

function CustomCalendar() {
  return (
    <Calendar aria-label="Custom calendar" className="w-72 rounded-2xl border border-border bg-surface p-3 shadow-sm">
      <Calendar.Header className="pb-3">
        <Calendar.Heading className="text-default" />
        <Calendar.NavButton slot="previous" className="text-default" />
        <Calendar.NavButton slot="next" className="text-default" />
      </Calendar.Header>
      <Calendar.Grid>
        <Calendar.GridHeader>
          {(day) => <Calendar.HeaderCell>{day}</Calendar.HeaderCell>}
        </Calendar.GridHeader>
        <Calendar.GridBody>
          {(date) => <Calendar.Cell date={date} />}
        </Calendar.GridBody>
      </Calendar.Grid>
    </Calendar>
  );
}

Customizing the component classes

@layer components {
  .calendar {
    @apply w-72 rounded-2xl border border-border bg-surface p-3 shadow-sm;
  }

  .calendar__heading {
    @apply text-sm font-semibold text-default-700;
  }

  .calendar__cell[data-selected="true"] {
    @apply bg-accent text-accent-foreground;
  }
}

CSS Classes

Calendar uses these classes in packages/styles/components/calendar.css and packages/styles/components/calendar-year-picker.css:

  • .calendar - Root container.
  • .calendar__header - Header row containing nav buttons and heading.
  • .calendar__heading - Current month label.
  • .calendar__nav-button - Previous/next navigation controls.
  • .calendar__grid - Main day grid.
  • .calendar__grid-header - Weekday header row wrapper.
  • .calendar__grid-body - Date rows wrapper.
  • .calendar__header-cell - Weekday header cell.
  • .calendar__cell - Interactive day cell.
  • .calendar__cell-indicator - Dot indicator inside a day cell.
  • .calendar-year-picker__trigger - Year picker toggle button.
  • .calendar-year-picker__trigger-heading - Heading text inside year picker trigger.
  • .calendar-year-picker__trigger-indicator - Indicator icon inside year picker trigger.
  • .calendar-year-picker__year-grid - Overlay grid of selectable years.
  • .calendar-year-picker__year-cell - Individual year option.

Interactive States

Calendar supports both pseudo-classes and React Aria data attributes:

  • Selected: [data-selected="true"]
  • Today: [data-today="true"]
  • Unavailable: [data-unavailable="true"]
  • Outside month: [data-outside-month="true"]
  • Hovered: :hover or [data-hovered="true"]
  • Pressed: :active or [data-pressed="true"]
  • Focus visible: :focus-visible or [data-focus-visible="true"]
  • Disabled: :disabled or [data-disabled="true"]

API Reference

Calendar Props

Calendar inherits all props from React Aria Calendar.

PropTypeDefaultDescription
selectionMode'single' | 'multiple''single'Whether one date or several dates can be selected.
valueDateValue | null | DateValue[]-Controlled selected date(s). An array when selectionMode="multiple".
defaultValueDateValue | null | DateValue[]-Initial selected date(s), uncontrolled. An array when selectionMode="multiple".
onChange(value: DateValue | DateValue[]) => void-Called when selection changes. Receives an array when selectionMode="multiple".
focusedValueDateValue-Controlled focused date.
onFocusChange(value: DateValue) => void-Called when focus moves to another date.
minValueDateValueCalendar-aware 1900-01-01Earliest selectable date.
maxValueDateValueCalendar-aware 2099-12-31Latest selectable date.
isDateUnavailable(date: DateValue) => boolean-Marks dates as unavailable.
isDisabledbooleanfalseDisables interaction and selection.
isReadOnlybooleanfalseKeeps content readable but prevents selection changes.
isInvalidbooleanfalseMarks the calendar as invalid for validation UI.
visibleDuration{months?: number}{months: 1}Number of visible months.
defaultYearPickerOpenbooleanfalseInitial open state of internal year picker.
isYearPickerOpenboolean-Controlled year picker open state.
onYearPickerOpenChange(isOpen: boolean) => void-Called when year picker open state changes.

Composition Parts

ComponentDescription
Calendar.HeaderHeader container for navigation and heading.
Calendar.HeadingCurrent month/year heading.
Calendar.NavButtonPrevious/next navigation control (slot=\"previous\" or slot=\"next\").
Calendar.GridDay grid for one month (offset supported for multi-month layouts).
Calendar.GridHeaderWeekday header container.
Calendar.GridBodyDate cell body container.
Calendar.HeaderCellWeekday label cell.
Calendar.CellIndividual date cell.
Calendar.CellIndicatorOptional indicator element for custom metadata.
Calendar.YearPickerTriggerTrigger to toggle year-picker mode.
Calendar.YearPickerTriggerHeadingLocalized heading content inside the year-picker trigger.
Calendar.YearPickerTriggerIndicatorToggle icon inside the year-picker trigger.
Calendar.YearPickerGridOverlay year selection grid container.
Calendar.YearPickerGridBodyBody renderer for year grid cells.
Calendar.YearPickerCellIndividual year option cell.

Calendar.Cell Render Props

When Calendar.Cell children is a function, React Aria render props are available:

PropTypeDescription
formattedDatestringLocalized day label for the cell.
isSelectedbooleanWhether the date is selected.
isUnavailablebooleanWhether the date is unavailable.
isDisabledbooleanWhether the cell is disabled.
isOutsideMonthbooleanWhether the date belongs to adjacent month.

For a complete list of supported calendar systems and their identifiers, see:

  • @internationalized/date — date types (CalendarDate, CalendarDateTime, ZonedDateTime) and utilities used by all date components
  • I18nProvider — override locale for a subtree
  • useLocale — read the current locale and layout direction

On this page