Calendar

Animated monthly calendar for single-day or range selection, with bounds, modifiers, locale support, and an optional DatePicker wrapper.

Installation

npx shadcn@latest add @iconiq/calendar

File Structure

Usage

"use client";

import { useState } from "react";
import { Calendar } from "@/components/ui/calendar";

export function CalendarPreview() {
  const [selected, setSelected] = useState<Date | null>(new Date());

  return (
    <Calendar
      onSelect={setSelected}
      selected={selected}
      size="md"
    />
  );
}

Props

Props
Description

Calendar

mode

Selection model. Use single for one date or range for start/end selection.

Type "single" | "range"·Default "single"

selected

Controlled selected day for single mode. Pass null to clear the highlight.

Type Date | null

defaultSelected

Initial selected day for uncontrolled single mode when selected is not provided.

Type Date | null

onSelect

Called when the user picks a day in single mode, including visible outside-month days.

Type (date: Date | null) => void

range

Controlled range for range mode. Shape is `{ from?: Date; to?: Date }`.

Type CalendarRange

defaultRange

Initial range for uncontrolled range mode.

Type CalendarRange

onRangeSelect

Called when the user updates the range in range mode.

Type (range: CalendarRange) => void

month

Controlled visible month. Prev/next, outside-day, and month/year picker navigation requests flow through onMonthChange.

Type Date

defaultMonth

Initial visible month for uncontrolled usage when month is not provided.

Type Date

onMonthChange

Called whenever the user navigates with prev/next, an outside day, or the month/year picker.

Type (month: Date) => void

disabled

Marks dates as non-interactive in addition to minDate/maxDate bounds.

Type (date: Date) => boolean

minDate

Earliest selectable day. Also disables month navigation into fully out-of-range months.

Type Date

maxDate

Latest selectable day. Also disables month navigation into fully out-of-range months.

Type Date

locale

Optional date-fns locale used for month labels, weekday headers, and spoken date labels.

Type Locale

labels

Override built-in English UI and accessibility strings such as Today, Clear, and picker labels.

Type Partial<CalendarLabels>

size

Controls the overall calendar scale, including the card width, spacing, nav controls, weekday row, and day cell sizing. Defaults to sm.

Type "sm" | "md" | "lg"

weekStartsOn

Overrides the first day of the week for both the weekday header and rendered month grid.

Type 0 | 1 | 2 | 3 | 4 | 5 | 6

minYear

Optional lower bound for selectable years in the year picker.

Type number

maxYear

Optional upper bound for selectable years in the year picker.

Type number

showOutsideDays

Whether leading and trailing days from adjacent months are rendered in the grid.

Type boolean·Default true

fixedWeeks

Pads the month grid to six weeks for consistent height. Only applies when showOutsideDays is true.

Type boolean·Default false

modifiers

Named matchers that render marker dots under matching days.

Type Record<string, (date: Date) => boolean>

modifierLabels

Human-readable names for modifier keys, appended to spoken day labels.

Type Record<string, string>

id

Optional root id used for heading and live-region relationships.

Type string

name

Optional native form field name. Renders a hidden input in single mode.

Type string

className

Optional class names applied to the root surface.

Type string

Date math and layout behavior

The grid is rebuilt with date-fns whenever the visible month changes.

The rendered range runs from startOfWeek(startOfMonth(currentMonth)) through endOfWeek(endOfMonth(currentMonth)). fixedWeeks pads the grid to six rows only when showOutsideDays is enabled.

Days outside the active month remain visible by default and can still be selected. Choosing one switches the visible month and selects that day, unless the date is unavailable.

Weekday headers and the grid start day follow the provided locale and weekStartsOn settings.

Selected days are highlighted even when they appear as outside-month cells in the current grid.

Motion and accessibility

Motion, keyboard support, and screen-reader semantics are built into the grid and picker overlays.

The root uses role=application with a role=grid date table, aria-selected day buttons, and a polite live selection summary.

Keyboard users can move through days with arrow keys, Home/End, PageUp/PageDown, and select with Enter or Space.

Month and year overlays trap focus, support arrow-key grid navigation, and return focus to the trigger on Escape.

Theme colors come from CSS variables, so the surface follows light/dark mode without client-side palette hydration.

Animations respect prefers-reduced-motion through useReducedMotion().

Registry bundle

Install the exact registry entry shown on the right when you want the component file and its declared runtime dependencies together.

Dependencies: motion, lucide-react, date-fns.

Contact

Additionally, if you find any bug or issue, feel free to raise an issue.

SuMoTuWeThFrSa
Wednesday, July 22nd, 2026