Components
Loading preview...
This Multi-Month Calendar component is a fully responsive, theme-aware date picker built on top of React DayPicker and styled with shadcn/ui. It supports both single-date selection and range selection, making it versatile for use cases like booking systems, scheduling tools, or analytics dashboards. The component highlights selected dates in a black-and-white scheme for maximum clarity across light and dark themes: single dates and range start/end points are shown with a solid black (light) or white (dark) background, while the range middle days are subtly marked with a lighter gray in light mode and a darker gray in dark mode. The design ensures a clean, modern look with smooth rounded edges for contiguous ranges and accessible focus states. Additional features include configurable number of calendars, year and month dropdowns, and a clear separation of demo and component code for easy integration. This makes it a robust, elegant solution for projects requiring a customizable multi-month calendar UI.
npx shadcn@latest add https://21st.dev/r/ruixen.ui/multi-month-calendar"use client";
import { useState } from "react";
import { MultiMonthCalendar } from "@/components/ui/multi-month-calendar";
import { DateRange } from "react-day-picker";
import { addDays } from "date-fns";
export default function DemoMultiMonthCalendar() {
const today = new Date();
// Range example
const [range, setRange] = useState<DateRange | undefined>({
from: today,
to: addDays(today, 3),
});
// Single date example
const [single, setSingle] = useState<Date | undefined>(today);
return (
<div className="flex flex-col gap-10 p-8">
<h1 className="text-xl font-semibold text-center">Multi-Month Calendar Demo</h1>
{/* Range Mode */}
<div className="flex flex-col items-center gap-4">
<h2 className="font-semibold">Range Mode</h2>
<MultiMonthCalendar
numberOfMonths={3}
mode="range"
selected={range}
onSelect={setRange}
/>
{range?.from && range?.to && (
<p className="text-sm text-muted-foreground">
Selected: {range.from.toDateString()} → {range.to.toDateString()}
</p>
)}
</div>
{/* Single Mode */}
<div className="flex flex-col items-center gap-4">
<h2 className="font-semibold">Single Date Mode</h2>
<MultiMonthCalendar
numberOfMonths={2}
mode="single"
selected={single}
onSelect={setSingle}
/>
{single && (
<p className="text-sm text-muted-foreground">
Selected: {single.toDateString()}
</p>
)}
</div>
</div>
);
}