Calendar
Browse dates in a clear, compact month view.
datefield
Preview
Calendar preview
Live · keyboard ready
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
Live · keyboard ready
October 2026
month-view-a-controlled-calendar-that-follows-the-month-the-user-navigates-to-.tsxtsx
Keyboard interactions
| Keys | Action |
|---|---|
| Arrow keys | Move by one day or one week, skipping blocked days and crossing months. |
| Home / End | Move to the start or end of the week. |
| PageUp / PageDown | Move by one month; with Shift, by one year. |
| Enter / Space | Selects 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.