Command Palette

Search for a command to run...

Github

Calendar

A calendar component that allows users to select a date or a range of dates.

May 2026
"use client";

import * as React from "react";

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

export function CalendarDemo() {
	const [date, setDate] = React.useState<Date | undefined>(new Date());

	return (
		<Calendar
			mode="single"
			selected={date}
			onSelect={setDate}
			className="rounded-lg border"
			captionLayout="dropdown"
		/>
	);
}

Installation

pnpm dlx shadcn@latest add https://herocn.dev/r/calendar.json

Usage

import { Calendar } from "@/components/ui/calendar"
const [date, setDate] = React.useState<Date | undefined>(new Date())

return (
  <Calendar
    mode="single"
    selected={date}
    onSelect={setDate}
    className="rounded-lg border"
  />
)

See the React DayPicker documentation for more information.

About

The Calendar component is built on top of React DayPicker.

Date Picker

You can use the <Calendar> component to build a date picker. See the Date Picker page for more information.

Examples

Basic

A basic calendar component. We used className="rounded-lg border" to style the calendar.

May 2026
"use client";

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

export function CalendarBasic() {
	return <Calendar mode="single" className="rounded-lg border" />;
}

Range Calendar

Use the mode="range" prop to enable range selection.

January 2026
February 2026
"use client";

import { addDays } from "date-fns";
import * as React from "react";
import type { DateRange } from "react-day-picker";

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

export function CalendarRange() {
	const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
		from: new Date(new Date().getFullYear(), 0, 12),
		to: addDays(new Date(new Date().getFullYear(), 0, 12), 30),
	});

	return (
		<Calendar
			mode="range"
			defaultMonth={dateRange?.from}
			selected={dateRange}
			onSelect={setDateRange}
			numberOfMonths={2}
			className="rounded-lg border"
		/>
	);
}

Month and Year Selector

Use captionLayout="dropdown" to show month and year dropdowns.

May 2026
"use client";

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

export function CalendarCaption() {
	return (
		<Calendar
			mode="single"
			captionLayout="dropdown"
			className="rounded-lg border"
		/>
	);
}

Presets

May 2026
"use client";

import { addDays } from "date-fns";
import * as React from "react";

import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import { Card, CardContent, CardFooter } from "@/components/ui/card";

export function CalendarWithPresets() {
	const [date, setDate] = React.useState<Date | undefined>(
		new Date(new Date().getFullYear(), 1, 12),
	);
	const [currentMonth, setCurrentMonth] = React.useState<Date>(
		new Date(new Date().getFullYear(), new Date().getMonth(), 1),
	);

	return (
		<Card className="mx-auto w-fit max-w-76" size="sm">
			<CardContent>
				<Calendar
					mode="single"
					selected={date}
					onSelect={setDate}
					month={currentMonth}
					onMonthChange={setCurrentMonth}
					fixedWeeks
					className="w-full p-0"
				/>
			</CardContent>
			<CardFooter className="flex flex-wrap gap-2 border-t">
				{[
					{ label: "Today", value: 0 },
					{ label: "Tomorrow", value: 1 },
					{ label: "In 3 days", value: 3 },
					{ label: "In a week", value: 7 },
					{ label: "In 2 weeks", value: 14 },
				].map((preset) => (
					<Button
						key={preset.value}
						variant="outline"
						size="sm"
						className="flex-1"
						onClick={() => {
							const newDate = addDays(new Date(), preset.value);
							setDate(newDate);
							setCurrentMonth(
								new Date(newDate.getFullYear(), newDate.getMonth(), 1),
							);
						}}
					>
						{preset.label}
					</Button>
				))}
			</CardFooter>
		</Card>
	);
}

Date and Time Picker

May 2026
"use client";

import { Clock2Icon } from "lucide-react";
import * as React from "react";

import { Calendar } from "@/components/ui/calendar";
import { Card, CardContent, CardFooter } from "@/components/ui/card";
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";
import {
	InputGroup,
	InputGroupAddon,
	InputGroupInput,
} from "@/components/ui/input-group";

export function CalendarWithTime() {
	const [date, setDate] = React.useState<Date | undefined>(
		new Date(new Date().getFullYear(), new Date().getMonth(), 12),
	);

	return (
		<Card size="sm" className="mx-auto w-fit">
			<CardContent>
				<Calendar
					mode="single"
					selected={date}
					onSelect={setDate}
					className="p-0"
				/>
			</CardContent>
			<CardFooter className="border-t bg-card">
				<FieldGroup>
					<Field>
						<FieldLabel htmlFor="time-from">Start Time</FieldLabel>
						<InputGroup>
							<InputGroupInput
								id="time-from"
								type="time"
								step="1"
								defaultValue="10:30:00"
								className="appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
							/>
							<InputGroupAddon>
								<Clock2Icon className="text-muted-foreground" />
							</InputGroupAddon>
						</InputGroup>
					</Field>
					<Field>
						<FieldLabel htmlFor="time-to">End Time</FieldLabel>
						<InputGroup>
							<InputGroupInput
								id="time-to"
								type="time"
								step="1"
								defaultValue="12:30:00"
								className="appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
							/>
							<InputGroupAddon>
								<Clock2Icon className="text-muted-foreground" />
							</InputGroupAddon>
						</InputGroup>
					</Field>
				</FieldGroup>
			</CardFooter>
		</Card>
	);
}

Booked dates

January 2026
"use client";

import * as React from "react";

import { Calendar } from "@/components/ui/calendar";
import { Card, CardContent } from "@/components/ui/card";

export function CalendarBookedDates() {
	const [date, setDate] = React.useState<Date | undefined>(
		new Date(new Date().getFullYear(), 0, 6),
	);
	const bookedDates = Array.from(
		{ length: 15 },
		(_, i) => new Date(new Date().getFullYear(), 0, 12 + i),
	);

	return (
		<Card className="mx-auto w-fit p-0">
			<CardContent className="p-0">
				<Calendar
					mode="single"
					defaultMonth={date}
					selected={date}
					onSelect={setDate}
					disabled={bookedDates}
					modifiers={{
						booked: bookedDates,
					}}
					modifiersClassNames={{
						booked: "[&>button]:line-through opacity-100",
					}}
				/>
			</CardContent>
		</Card>
	);
}

Custom Cell Size

You can customize the size of calendar cells using the --cell-size CSS variable.

December 2026
"use client";

import { addDays } from "date-fns";
import * as React from "react";
import type { DateRange } from "react-day-picker";

import {
	Calendar,
	CalendarDayButton,
} from "@/components/ui/calendar";
import { Card, CardContent } from "@/components/ui/card";

export function CalendarCustomDays() {
	const [range, setRange] = React.useState<DateRange | undefined>({
		from: new Date(new Date().getFullYear(), 11, 8),
		to: addDays(new Date(new Date().getFullYear(), 11, 8), 10),
	});

	return (
		<Card className="mx-auto w-fit p-0">
			<CardContent className="p-0">
				<Calendar
					mode="range"
					defaultMonth={range?.from}
					selected={range}
					onSelect={setRange}
					numberOfMonths={1}
					captionLayout="dropdown"
					className="[--cell-size:--spacing(10)] md:[--cell-size:--spacing(12)]"
					formatters={{
						formatMonthDropdown: (date) => {
							return date.toLocaleString("default", { month: "long" });
						},
					}}
					components={{
						DayButton: ({ children, modifiers, day, ...props }) => {
							const isWeekend =
								day.date.getDay() === 0 || day.date.getDay() === 6;

							return (
								<CalendarDayButton day={day} modifiers={modifiers} {...props}>
									{children}
									{!modifiers.outside && (
										<span>{isWeekend ? "$120" : "$100"}</span>
									)}
								</CalendarDayButton>
							);
						},
					}}
				/>
			</CardContent>
		</Card>
	);
}

Week Numbers

Use showWeekNumber to show week numbers.

January 2026
01
02
03
04
05
"use client";

import * as React from "react";

import { Calendar } from "@/components/ui/calendar";
import { Card, CardContent } from "@/components/ui/card";

export function CalendarWeekNumbers() {
	const [date, setDate] = React.useState<Date | undefined>(
		new Date(new Date().getFullYear(), 0, 12),
	);

	return (
		<Card className="mx-auto w-fit p-0">
			<CardContent className="p-0">
				<Calendar
					mode="single"
					defaultMonth={date}
					selected={date}
					onSelect={setDate}
					showWeekNumber
				/>
			</CardContent>
		</Card>
	);
}

RTL

مايو 2026
"use client";

import * as React from "react";
import { arSA, he } from "react-day-picker/locale";

import {
	type Translations,
	useTranslation,
} from "@/components/language-selector";
import { Calendar } from "@/components/ui/calendar";

const translations: Translations = {
	en: {
		dir: "ltr",
		values: {},
	},
	ar: {
		dir: "rtl",
		values: {},
	},
	he: {
		dir: "rtl",
		values: {},
	},
};

const locales = {
	ar: arSA,
	he: he,
} as const;

export function CalendarRtl() {
	const { dir, language } = useTranslation(translations, "ar");
	const [date, setDate] = React.useState<Date | undefined>(new Date());

	return (
		<Calendar
			mode="single"
			selected={date}
			onSelect={setDate}
			className="rounded-lg border [--cell-size:--spacing(9)]"
			captionLayout="dropdown"
			dir={dir}
			locale={
				dir === "rtl" ? locales[language as keyof typeof locales] : undefined
			}
		/>
	);
}

To enable RTL support, import the locale from react-day-picker/locale and pass both the locale and dir props to the Calendar component:

import { arSA } from "react-day-picker/locale"

<Calendar
  mode="single"
  selected={date}
  onSelect={setDate}
  locale={arSA}
  dir="rtl"
/>

Reference

Props

The Calendar component accepts all props from react-day-picker DayPicker plus the following:

PropTypeDefault