Calendar

Browse dates in a clear, compact month view.

datefield
Preview
Calendar preview

October 2026

When to use

  • Inline date picking where the month should stay visible, such as booking pages.
  • Picking one date with blocked days via minDate, maxDate, and disabledDates.

When not to use

  • Use date-picker for a form field that opens a calendar popover.
  • Use time-picker for times of day.
  • Use booking-pill for a full compact booking flow.

shadcn CLI

Also installs (1)

  • manicat-foundation
Manual install(+)
registry.jsonjson
{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "calendar",
  "type": "registry:ui",
  "title": "Calendar",
  "description": "Browse dates in a clear, compact month view.",
  "categories": [
    "inputs"
  ],
  "dependencies": [
    "lucide-react",
    "motion"
  ],
  "registryDependencies": [
    "https://manicat.viraza.net/r/manicat-foundation.json"
  ],
  "files": [
    {
      "path": "registry/components/calendar/calendar.tsx",
      "type": "registry:component",
      "target": "@components/manicat/calendar/calendar.tsx"
    },
    {
      "path": "registry/components/calendar/calendar.module.css",
      "type": "registry:component",
      "target": "@components/manicat/calendar/calendar.module.css"
    }
  ],
  "docs": "Docs and live preview: https://uiarc.dev/components/calendar",
  "meta": {
    "tier": "free",
    "kind": "component",
    "docs": "https://manicat.viraza.net/components/calendar",
    "markdown": "https://uiarc.dev/components/calendar/markdown",
    "tags": [
      "date",
      "field"
    ]
  }
}

Usage

Install the component, then copy this into your app. Change the content and the props to fit your screen.

example.tsxtsx
"use client";

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

export function CalendarExample() {
  const [value, setValue] = useState<Date | undefined>(new Date(2026, 9, 5));

  return <Calendar value={value} onChange={setValue} month={new Date(2026, 9, 1)} onMonthChange={() => {}} showToday />;
}

Examples

Real screens rather than isolated props. Switch to Code to copy a whole example into your project.

Month view A controlled calendar that follows the month the user navigates to.

Month view A controlled calendar that follows the month the user navigates to. preview

October 2026

Keyboard interactions

KeysAction
Arrow keysMove by one day or one week, skipping blocked days and crossing months.
Home / EndMove to the start or end of the week.
PageUp / PageDownMove by one month; with Shift, by one year.
Enter / SpaceSelects the focused day.

Accessibility

  • Days sit in a role="grid" with role="row" and role="gridcell" buttons carrying full date aria-labels, aria-selected, and aria-current="date" for today.
  • Roving tabindex keeps one day in the tab order; month changes are announced through a polite live region.
  • Previous and next buttons are labelled and use aria-disabled at the min or max month.

Motion

  • Months slide in the direction of travel while the title letters and year digits roll; the selection highlight glides between days on the morph spring.
  • Reduced motion, applied after hydration, swaps months and moves the highlight instantly.

Responsive behavior

  • The calendar is min(100%, 328px) wide and days are square cells that scale with it.
  • The header is a container query: below 260px the title takes its own row and the controls move under it.

Performance

  • Only the incoming month is observed with a ResizeObserver, to morph between four, five, and six rows.
  • Each day is a button, so a month is about 42 cells; render one calendar rather than many side by side.

Notes for AI

  • Use inline where the calendar is always visible, such as booking pages. Use date-picker for a form field that opens a calendar popover.
  • value is controlled only; month can be controlled or left internal.
  • Also exports date helpers addDays, addMonths, sameDay, and startOfDay, and the CalendarDateMatcher type.