Calendar [React Day Picker] | Community Components | 21st
Origin UI/Calendar [React Day Picker]/Range calendar with presets
Search K
Pricing Sign in
Calendar [React Day Picker]
Calendar [React Day Picker]
Origin UI](/content/@originui/library/origin-ui/index.html) by Origin UI](/content/@originui/index.html)
Copy prompt
SaveRemixCLIReport
SaveCopy prompt
PreviewCodeInfo
React App
TodayYesterdayLast 7 daysLast 30 daysMonth to dateLast monthYear to dateLast year
August 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 26 | 27 | 28 | 29 | 30 | 31 | 1 |
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 | 1 | 2 | 3 | 4 | 5 |
Range calendar with presets - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import {
endOfMonth,
endOfYear,
startOfMonth,
startOfYear,
subDays,
subMonths,
subYears,
} from "date-fns";
import { useState } from "react";
import { DateRange } from "react-day-picker";
function Component() {
const today = new Date();
const yesterday = {
from: subDays(today, 1),
to: subDays(today, 1),
};
const last7Days = {
from: subDays(today, 6),
to: today,
};
const last30Days = {
from: subDays(today, 29),
to: today,
};
const monthToDate = {
from: startOfMonth(today),
to: today,
};
const lastMonth = {
from: startOfMonth(subMonths(today, 1)),
to: endOfMonth(subMonths(today, 1)),
};
const yearToDate = {
from: startOfYear(today),
to: today,
};
const lastYear = {
from: startOfYear(subYears(today, 1)),
to: endOfYear(subYears(today, 1)),
};
const [month, setMonth] = useState(today);
const [date, setDate] = useState<DateRange | undefined>(last7Days);
return (
<div>
<div className="rounded-lg border border-border">
<div className="flex max-sm:flex-col">
<div className="relative border-border py-4 max-sm:order-1 max-sm:border-t sm:w-32">
<div className="h-full border-border sm:border-e">
<div className="flex flex-col px-2">
<Button
variant="ghost"
size="sm"
className="w-full justify-start"
onClick={() => {
setDate({
from: today,
to: today,
});
setMonth(today);
}}
>
Today
</Button>
<Button
variant="ghost"
size="sm"
className="w-full justify-start"
onClick={() => {
setDate(yesterday);
setMonth(yesterday.to);
}}
>
Yesterday
</Button>
<Button
variant="ghost"
size="sm"
className="w-full justify-start"
onClick={() => {
setDate(last7Days);
setMonth(last7Days.to);
}}
>
Last 7 days
</Button>
<Button
variant="ghost"
size="sm"
className="w-full justify-start"
onClick={() => {
setDate(last30Days);
setMonth(last30Days.to);
}}
>
Last 30 days
</Button>
<Button
variant="ghost"
size="sm"
className="w-full justify-start"
onClick={() => {
setDate(monthToDate);
setMonth(monthToDate.to);
}}
>
Month to date
</Button>
<Button
variant="ghost"
size="sm"
className="w-full justify-start"
onClick={() => {
setDate(lastMonth);
setMonth(lastMonth.to);
}}
>
Last month
</Button>
<Button
variant="ghost"
size="sm"
className="w-full justify-start"
onClick={() => {
setDate(yearToDate);
setMonth(yearToDate.to);
}}
>
Year to date
</Button>
<Button
variant="ghost"
size="sm"
className="w-full justify-start"
onClick={() => {
setDate(lastYear);
setMonth(lastYear.to);
}}
>
Last year
</Button>
</div>
</div>
</div>
<Calendar
mode="range"
selected={date}
onSelect={(newDate) => {
if (newDate) {
setDate(newDate);
}
}}
month={month}
onMonthChange={setMonth}
className="p-2 bg-background"
disabled={[\
{ after: today },\
]}
/>
</div>
</div>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Range calendar with presets -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
More examples
Default Open page →
React App
August 2026
Calendar - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { Calendar } from "@/components/ui/calendar";
import { useState } from "react";
function Component() {
const [date, setDate] = useState<Date | undefined>(new Date());
return (
<div>
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="rounded-lg border border-border p-2"
/>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Calendar -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Range calendar Open page →
React App
August 2026
Range calendar - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { Calendar } from "@/components/ui/calendar";
import { addDays } from "date-fns";
import { useState } from "react";
import { DateRange } from "react-day-picker";
function Component() {
const today = new Date();
const [date, setDate] = useState<DateRange | undefined>({
from: today,
to: addDays(today, 3),
});
return (
<div>
<Calendar
mode="range"
selected={date}
onSelect={setDate}
className="rounded-lg border border-border p-2"
/>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Range calendar -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Disabled dates Open page →
React App
August 2026
Disabled dates - React DayPicker
Usage.tsxComponent.tsx
Copy
import { Calendar } from "@/components/ui/calendar";
import { addDays } from "date-fns";
function Component() {
const today = new Date();
return (
<div>
<Calendar
mode="range"
disabled={[\
{ before: new Date() },\
new Date(),\
{ dayOfWeek: [0, 6] },\
{\
from: addDays(today, 14),\
to: addDays(today, 16),\
},\
{\
from: addDays(today, 23),\
to: addDays(today, 24),\
},\
]}
excludeDisabled
className="rounded-lg border border-border p-2 bg-background"
/>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Disabled dates -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Multiple day selection Open page →
React App
August 2026
Multiple day selection - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { Calendar } from "@/components/ui/calendar";
import { addDays, subDays } from "date-fns";
import { useState } from "react";
function Component() {
const today = new Date();
const [date, setDate] = useState<Date[] | undefined>([\
subDays(today, 17),\
addDays(today, 2),\
addDays(today, 6),\
addDays(today, 8),\
]);
return (
<div>
<Calendar
mode="multiple"
selected={date}
onSelect={setDate}
className="rounded-lg border border-border p-2 bg-background"
/>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Multiple day selection -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Custom select day style Open page →
React App
August 2026
Custom select day style - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { Calendar } from "@/components/ui/calendar";
import { useState } from "react";
function Component() {
const [date, setDate] = useState<Date | undefined>(new Date());
return (
<div>
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="rounded-lg border border-border p-2 bg-background"
classNames={{
day_button: "rounded-full",
}}
/>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Custom select day style -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Right navigation Open page →
React App
August 2026
Right navigation - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { Calendar } from "@/components/ui/calendar";
import { useState } from "react";
function Component() {
const [date, setDate] = useState<Date | undefined>(new Date());
return (
<div>
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="rounded-lg border border-border p-2 bg-background"
classNames={{
month_caption: "ms-2.5 me-20 justify-start",
nav: "justify-end",
}}
/>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Right navigation -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Monthly / yearly selects Open page →
React App
August2026August 2026
Monthly / yearly selects - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { Calendar } from "@/components/ui/calendar";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { useState } from "react";
import { DropdownNavProps, DropdownProps } from "react-day-picker";
function Component() {
const [date, setDate] = useState<Date | undefined>(new Date());
const handleCalendarChange = (
_value: string | number,
_e: React.ChangeEventHandler<HTMLSelectElement>,
) => {
const _event = {
target: {
value: String(_value),
},
} as React.ChangeEvent<HTMLSelectElement>;
_e(_event);
};
return (
<div>
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="rounded-lg border border-border p-2 bg-background"
classNames={{
month_caption: "mx-0",
}}
captionLayout="dropdown"
defaultMonth={new Date()}
startMonth={new Date(1980, 6)}
hideNavigation
components={{
DropdownNav: (props: DropdownNavProps) => {
return <div className="flex w-full items-center gap-2">{props.children}</div>;
},
Dropdown: (props: DropdownProps) => {
return (
<Select
value={String(props.value)}
onValueChange={(value) => {
if (props.onChange) {
handleCalendarChange(value, props.onChange);
}
}}
>
<SelectTrigger className="h-8 w-fit font-medium first:grow">
<SelectValue />
</SelectTrigger>
<SelectContent className="max-h-[min(26rem,var(--radix-select-content-available-height))]">
{props.options?.map((option) => (
<SelectItem
key={option.value}
value={String(option.value)}
disabled={option.disabled}
>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
);
},
}}
/>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Monthly / yearly selects -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Yearly select + nav Open page →
React App
August2026August 2026
Yearly select + nav - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
function Component() {
const [date, setDate] = useState<Date | undefined>(new Date());
return (
<div>
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="rounded-lg border border-border p-2 bg-background"
captionLayout="dropdown-years"
defaultMonth={new Date()}
startMonth={new Date(1980, 6)}
components={{
DropdownNav: (props: DropdownNavProps) => {
return (
<div className="flex w-full items-center justify-center gap-3 [&>span]:text-sm [&>span]:font-medium">
{props.children}
</div>
);
},
YearsDropdown: (props: DropdownProps) => {
return (
<Select
value={String(props.value)}
onValueChange={(value) => {
if (props.onChange) {
handleCalendarChange(value, props.onChange);
}
}}
>
<SelectTrigger className="h-8 w-fit font-medium">
<SelectValue />
</SelectTrigger>
<SelectContent className="max-h-[min(26rem,var(--radix-select-content-available-height))]">
{props.options?.map((option) => (
<SelectItem
key={option.value}
value={String(option.value)}
disabled={option.disabled}
>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
);
},
}}
/>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Yearly select + nav -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Weekly numbers Open page →
React App
August 2026
| Su | Mo | Tu | We | Th | Fr | Sa | |
|---|---|---|---|---|---|---|---|
| 31 | 26 | 27 | 28 | 29 | 30 | 31 | 1 |
| 32 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 33 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 34 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 35 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 36 | 30 | 31 | 1 | 2 | 3 | 4 | 5 |
Weekly numbers - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { Calendar } from "@/components/ui/calendar";
import { useState } from "react";
import type { WeekNumberProps } from "react-day-picker";
function Component() {
const [date, setDate] = useState<Date | undefined>(new Date());
return (
<div>
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="rounded-lg border border-border p-2 bg-background"
fixedWeeks
showWeekNumber
components={{
WeekNumber: ({ week, ...props }: WeekNumberProps) => {
return <th {...props}>{week.weekNumber}</th>;
},
}}
/>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Weekly numbers -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
With button Open page →
React App
July 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 28 | 29 | 30 | 1 | 2 | 3 | 4 |
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 | 1 |
Today
With button - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import { addDays } from "date-fns";
import { useState } from "react";
function Component() {
const today = new Date();
const selectedDay = addDays(today, -28);
const [month, setMonth] = useState(selectedDay);
const [date, setDate] = useState<Date | undefined>(selectedDay);
return (
<div>
<div className="rounded-lg border border-border p-2">
<Calendar
className="bg-background"
mode="single"
selected={date}
onSelect={setDate}
month={month}
onMonthChange={setMonth}
/>
<Button
variant="outline"
size="sm"
className="my-1"
onClick={() => {
setDate(today);
setMonth(today);
}}
>
Today
</Button>
</div>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
With button -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
With today button Open page →
React App
July 2026
Today
With button - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
export { Component };
With date input Open page →
React App
August 2026
Enter date
Date input - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { Calendar } from "@/components/ui/calendar";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { format } from "date-fns";
import { CalendarIcon } from "lucide-react";
import { useEffect, useId, useState } from "react";
function Component() {
const id = useId();
const today = new Date();
const [month, setMonth] = useState(today);
const [date, setDate] = useState<Date | undefined>(today);
const [inputValue, setInputValue] = useState("");
const handleDayPickerSelect = (date: Date | undefined) => {
if (!date) {
setInputValue("");
setDate(undefined);
} else {
setDate(date);
setMonth(date);
setInputValue(format(date, "yyyy-MM-dd"));
}
};
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setInputValue(value);
if (value) {
const parsedDate = new Date(value);
setDate(parsedDate);
setMonth(parsedDate);
} else {
setDate(undefined);
}
};
useEffect(() => {
setInputValue(format(today, "yyyy-MM-dd"));
}, []);
return (
<div>
<div className="rounded-lg border border-border">
<Calendar
mode="single"
className="p-2 bg-background"
selected={date}
onSelect={handleDayPickerSelect}
month={month}
onMonthChange={setMonth}
/>
<div className="border-t border-border p-3">
<div className="flex items-center gap-3">
<Label htmlFor={id} className="text-xs">
Enter date
</Label>
<div className="relative grow">
<Input
id={id}
type="date"
value={inputValue}
onChange={handleInputChange}
className="peer ps-9 [&::-webkit-calendar-picker-indicator]:hidden"
aria-label="Select date"
/>
<div className="pointer-events-none absolute inset-y-0 start-0 flex items-center justify-center ps-3 text-muted-foreground/80 peer-disabled:opacity-50">
<CalendarIcon size={16} strokeWidth={2} aria-hidden="true" />
</div>
</div>
</div>
</div>
</div>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Date input -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
With time input Open page →
React App
August 2026
Enter time
Time input - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { Calendar } from "@/components/ui/calendar";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Clock } from "lucide-react";
import { useId, useState } from "react";
function Component() {
const id = useId();
const [date, setDate] = useState<Date | undefined>(new Date());
return (
<div>
<div className="rounded-lg border border-border">
<Calendar mode="single" className="p-2 bg-background" selected={date} onSelect={setDate} />
<div className="border-t border-border p-3">
<div className="flex items-center gap-3">
<Label htmlFor={id} className="text-xs">
Enter time
</Label>
<div className="relative grow">
<Input
id={id}
type="time"
step="1"
defaultValue="12:00:00"
className="peer ps-9 [&::-webkit-calendar-picker-indicator]:hidden"
/>
<div className="pointer-events-none absolute inset-y-0 start-0 flex items-center justify-center ps-3 text-muted-foreground/80 peer-disabled:opacity-50">
<Clock size={16} strokeWidth={2} aria-hidden="true" />
</div>
</div>
</div>
</div>
</div>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Time input -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Advanced selection Open page →
React App
August 2026
Advanced selection - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
eachMonthOfInterval,
eachYearOfInterval,
endOfYear,
format,
isAfter,
isBefore,
startOfYear,
} from "date-fns";
import { ChevronDown } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { CaptionLabelProps, MonthGridProps } from "react-day-picker";
function Component() {
const today = new Date();
const [month, setMonth] = useState(today);
const [date, setDate] = useState<Date | undefined>(today);
const [isYearView, setIsYearView] = useState(false);
const startDate = new Date(1980, 6);
const endDate = new Date(2030, 6);
const years = eachYearOfInterval({
start: startOfYear(startDate),
end: endOfYear(endDate),
});
return (
<div>
<Calendar
mode="single"
selected={date}
onSelect={setDate}
month={month}
onMonthChange={setMonth}
defaultMonth={new Date()}
startMonth={startDate}
endMonth={endDate}
className="overflow-hidden rounded-lg border border-border p-2 bg-background"
classNames={{
month_caption: "ms-2.5 me-20 justify-start",
nav: "justify-end",
}}
components={{
CaptionLabel: (props: CaptionLabelProps) => (
<CaptionLabel isYearView={isYearView} setIsYearView={setIsYearView} {...props} />
),
MonthGrid: (props: MonthGridProps) => {
return (
<MonthGrid
className={props.className}
isYearView={isYearView}
setIsYearView={setIsYearView}
startDate={startDate}
endDate={endDate}
years={years}
currentYear={month.getFullYear()}
currentMonth={month.getMonth()}
onMonthSelect={(selectedMonth: Date) => {
setMonth(selectedMonth);
setIsYearView(false);
}}
>
{props.children}
</MonthGrid>
);
},
}}
/>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Advanced selection -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
function MonthGrid({
className,
children,
isYearView,
startDate,
endDate,
years,
currentYear,
currentMonth,
onMonthSelect,
}: {
className?: string;
children: React.ReactNode;
isYearView: boolean;
setIsYearView: React.Dispatch<React.SetStateAction<boolean>>;
startDate: Date;
endDate: Date;
years: Date[];
currentYear: number;
currentMonth: number;
onMonthSelect: (date: Date) => void;
}) {
const currentYearRef = useRef<HTMLDivElement>(null);
const currentMonthButtonRef = useRef<HTMLButtonElement>(null);
const scrollAreaRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (isYearView && currentYearRef.current && scrollAreaRef.current) {
const viewport = scrollAreaRef.current.querySelector(
"[data-radix-scroll-area-viewport]",
) as HTMLElement;
if (viewport) {
const yearTop = currentYearRef.current.offsetTop;
viewport.scrollTop = yearTop;
}
setTimeout(() => {
currentMonthButtonRef.current?.focus();
}, 100);
}
}, [isYearView]);
return (
<div className="relative">
<table className={className}>{children}</table>
{isYearView && (
<div className="absolute inset-0 z-20 -mx-2 -mb-2 bg-background">
<ScrollArea ref={scrollAreaRef} className="h-full">
{years.map((year) => {
const months = eachMonthOfInterval({
start: startOfYear(year),
end: endOfYear(year),
});
const isCurrentYear = year.getFullYear() === currentYear;
return (
<div key={year.getFullYear()} ref={isCurrentYear ? currentYearRef : undefined}>
<CollapsibleYear title={year.getFullYear().toString()} open={isCurrentYear}>
<div className="grid grid-cols-3 gap-2">
{months.map((month) => {
const isDisabled = isBefore(month, startDate) || isAfter(month, endDate);
const isCurrentMonth =
month.getMonth() === currentMonth && year.getFullYear() === currentYear;
return (
<Button
key={month.getTime()}
ref={isCurrentMonth ? currentMonthButtonRef : undefined}
variant={isCurrentMonth ? "default" : "outline"}
size="sm"
className="h-7"
disabled={isDisabled}
onClick={() => onMonthSelect(month)}
>
{format(month, "MMM")}
</Button>
);
})}
</div>
</CollapsibleYear>
</div>
);
})}
</ScrollArea>
</div>
)}
</div>
);
}
function CaptionLabel({
children,
isYearView,
setIsYearView,
}: {
isYearView: boolean;
setIsYearView: React.Dispatch<React.SetStateAction<boolean>>;
} & React.HTMLAttributes<HTMLSpanElement>) {
return (
<Button
className="-ms-2 flex items-center gap-2 text-sm font-medium hover:bg-transparent data-[state=open]:text-muted-foreground/80 [&[data-state=open]>svg]:rotate-180"
variant="ghost"
size="sm"
onClick={() => setIsYearView((prev) => !prev)}
data-state={isYearView ? "open" : "closed"}
>
{children}
<ChevronDown
size={16}
strokeWidth={2}
className="shrink-0 text-muted-foreground/80 transition-transform duration-200"
aria-hidden="true"
/>
</Button>
);
}
function CollapsibleYear({
title,
children,
open,
}: {
title: string;
children: React.ReactNode;
open?: boolean;
}) {
return (
<Collapsible className="border-t border-border px-2 py-1.5" defaultOpen={open}>
<CollapsibleTrigger asChild>
<Button
className="flex w-full justify-start gap-2 text-sm font-medium hover:bg-transparent [&[data-state=open]>svg]:rotate-180"
variant="ghost"
size="sm"
>
<ChevronDown
size={16}
strokeWidth={2}
className="shrink-0 text-muted-foreground/80 transition-transform duration-200"
aria-hidden="true"
/>
{title}
</Button>
</CollapsibleTrigger>
<CollapsibleContent className="overflow-hidden px-3 py-1 text-sm transition-all data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down">
{children}
</CollapsibleContent>
</Collapsible>
);
}
export { Component };
Appointment picker Open page →
React App
August 2026
Friday, 7
09:0009:3010:0010:3011:0011:3012:0012:3013:0013:3014:0014:3015:0015:3016:0016:3017:0017:30
Appointment picker - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import { ScrollArea } from "@/components/ui/scroll-area";
import { format } from "date-fns";
import { useState } from "react";
function Component() {
const today = new Date();
const [date, setDate] = useState<Date>(today);
const [time, setTime] = useState<string | null>(null);
const timeSlots = [\
{ time: "09:00", available: false },\
{ time: "09:30", available: false },\
{ time: "10:00", available: true },\
{ time: "10:30", available: true },\
{ time: "11:00", available: true },\
{ time: "11:30", available: true },\
{ time: "12:00", available: false },\
{ time: "12:30", available: true },\
{ time: "13:00", available: true },\
{ time: "13:30", available: true },\
{ time: "14:00", available: true },\
{ time: "14:30", available: false },\
{ time: "15:00", available: false },\
{ time: "15:30", available: true },\
{ time: "16:00", available: true },\
{ time: "16:30", available: true },\
{ time: "17:00", available: true },\
{ time: "17:30", available: true },\
];
return (
<div>
<div className="rounded-lg border border-border">
<div className="flex max-sm:flex-col">
<Calendar
mode="single"
selected={date}
onSelect={(newDate) => {
if (newDate) {
setDate(newDate);
setTime(null);
}
}}
className="p-2 sm:pe-5 bg-background"
disabled={[\
{ before: today },\
]}
/>
<div className="relative w-full max-sm:h-48 sm:w-40">
<div className="absolute inset-0 border-border py-4 max-sm:border-t">
<ScrollArea className="h-full border-border sm:border-s">
<div className="space-y-3">
<div className="flex h-5 shrink-0 items-center px-5">
<p className="text-sm font-medium">{format(date, "EEEE, d")}</p>
</div>
<div className="grid gap-1.5 px-5 max-sm:grid-cols-2">
{timeSlots.map(({ time: timeSlot, available }) => (
<Button
key={timeSlot}
variant={time === timeSlot ? "default" : "outline"}
size="sm"
className="w-full"
onClick={() => setTime(timeSlot)}
disabled={!available}
>
{timeSlot}
</Button>
))}
</div>
</div>
</ScrollArea>
</div>
</div>
</div>
</div>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Appointment picker -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Calendar with presets Open page →
React App
TodayYesterdayLast weekLast monthLast year
August 2026
Calendar with presets - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import { subDays, subMonths, subYears } from "date-fns";
import { useState } from "react";
function Component() {
const today = new Date();
const yesterday = subDays(today, 1);
const lastWeek = subDays(today, 7);
const lastMonth = subMonths(today, 1);
const lastYear = subYears(today, 1);
const [month, setMonth] = useState(today);
const [date, setDate] = useState<Date>(today);
return (
<div>
<div className="rounded-lg border border-border">
<div className="flex max-sm:flex-col">
<div className="relative border-border py-4 max-sm:order-1 max-sm:border-t sm:w-32">
<div className="h-full border-border sm:border-e">
<div className="flex flex-col px-2">
<Button
variant="ghost"
size="sm"
className="w-full justify-start"
onClick={() => {
setDate(today);
setMonth(today);
}}
>
Today
</Button>
<Button
variant="ghost"
size="sm"
className="w-full justify-start"
onClick={() => {
setDate(yesterday);
setMonth(yesterday);
}}
>
Yesterday
</Button>
<Button
variant="ghost"
size="sm"
className="w-full justify-start"
onClick={() => {
setDate(lastWeek);
setMonth(lastWeek);
}}
>
Last week
</Button>
<Button
variant="ghost"
size="sm"
className="w-full justify-start"
onClick={() => {
setDate(lastMonth);
setMonth(lastMonth);
}}
>
Last month
</Button>
<Button
variant="ghost"
size="sm"
className="w-full justify-start"
onClick={() => {
setDate(lastYear);
setMonth(lastYear);
}}
>
Last year
</Button>
</div>
</div>
</div>
<Calendar
mode="single"
selected={date}
onSelect={(newDate) => {
if (newDate) {
setDate(newDate);
}
}}
month={month}
onMonthChange={setMonth}
className="p-2 bg-background"
disabled={[\
{ after: today },\
]}
/>
</div>
</div>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Calendar with presets -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Two months calendar Open page →
React App
August 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 |
September 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | ||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 |
Two months calendar - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
function Component() {
const today = new Date();
const [date, setDate] = useState<DateRange | undefined>({
from: today,
to: addDays(today, 25),
});
return (
<div>
<Calendar
mode="range"
selected={date}
onSelect={setDate}
numberOfMonths={2}
pagedNavigation
showOutsideDays={false}
className="rounded-lg border border-border p-2 bg-background"
classNames={{
months: "gap-8",
month:
"relative first-of-type:before:hidden before:absolute max-sm:before:inset-x-2 max-sm:before:h-px max-sm:before:-top-2 sm:before:inset-y-2 sm:before:w-px before:bg-border sm:before:-left-4",
}}
/>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Two months calendar -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Three months calendar Open page →
React App
August 2026
September 2026
October 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
Three months calendar - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
function Component() {
const today = new Date();
const [date, setDate] = useState<DateRange | undefined>({
from: today,
to: addDays(today, 48),
});
return (
<div>
<Calendar
mode="range"
selected={date}
onSelect={setDate}
numberOfMonths={3}
pagedNavigation
showOutsideDays={false}
className="rounded-lg border border-border p-2 bg-background"
classNames={{
months: "sm:flex-col md:flex-row gap-8",
month:
"relative first-of-type:before:hidden before:absolute max-md:before:inset-x-2 max-md:before:h-px max-md:before:-top-4 md:before:inset-y-2 md:before:w-px before:bg-border md:before:-left-4",
}}
/>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Three months calendar -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Pricing calendar Open page →
React App
August 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7$118 | 8$147 |
| 9$193 | 10$164 | 11$104 | 12$171 | 13$108 | 14$100 | 15$194 |
| 16$119 | 17$173 | 18$186 | 19$130 | 20$145 | 21$199 | 22$154 |
| 23$151 | 24$191 | 25$175 | 26$152 | 27$176 | 28$137 | 29$193 |
| 30$128 | 31$145 |
September 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 1$155 | 2$187 | 3$154 | 4$110 | 5$107 | ||
| 6$101 | 7$174 | 8$183 | 9$174 | 10$135 | 11$162 | 12$92 |
| 13$141 | 14$131 | 15$80 | 16$189 | 17$192 | 18$145 | 19$177 |
| 20$146 | 21$93 | 22$136 | 23$127 | 24$158 | 25$144 | 26$86 |
| 27$179 | 28$87 | 29$190 | 30$157 |
Pricing calendar - React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { cn } from "@/lib/utils";
import { Calendar } from "@/components/ui/calendar";
import { format } from "date-fns";
import { useEffect, useState } from "react";
import { DayButtonProps } from "react-day-picker";
const GOOD_PRICE_THRESHOLD = 100;
function Component() {
const today = new Date();
const [date, setDate] = useState<Date | undefined>(today);
const [mockPriceData, setMockPriceData] = useState<Record<string, number>>({});
useEffect(() => {
const generateMockPriceData = () => {
const data: Record<string, number> = {};
for (let i = 0; i < 180; i++) {
const date = new Date(today);
date.setDate(today.getDate() + i);
const dateKey = format(date, "yyyy-MM-dd");
const randomPrice = Math.floor(Math.random() * (200 - 80 + 1)) + 80;
data[dateKey] = randomPrice;
}
return data;
};
setMockPriceData(generateMockPriceData());
}, []);
const isDateDisabled = (date: Date) => {
return !mockPriceData[format(date, "yyyy-MM-dd")];
};
return (
<div>
<Calendar
mode="single"
selected={date}
onSelect={setDate}
numberOfMonths={2}
pagedNavigation
showOutsideDays={false}
className="rounded-lg border border-border p-2 bg-background"
classNames={{
months: "sm:flex-col md:flex-row gap-8",
month:
"relative first-of-type:before:hidden before:absolute max-md:before:inset-x-2 max-md:before:inset-y-2 md:before:w-px before:bg-border md:before:-left-4",
weekday: "w-12",
day_button: "size-12",
today: "*:after:hidden",
}}
components={{
DayButton: (props: DayButtonProps) => <DayButton {...props} prices={mockPriceData} />,
}}
disabled={isDateDisabled}
/>
<p
className="mt-4 text-center text-xs text-muted-foreground"
role="region"
aria-live="polite"
>
Pricing calendar -{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
function DayButton(props: DayButtonProps & { prices: Record<string, number> }) {
const { day, modifiers, prices, ...buttonProps } = props;
const price = prices[format(day.date, "yyyy-MM-dd")];
const isGoodPrice = price < GOOD_PRICE_THRESHOLD;
return (
<button {...buttonProps}>
<span className="flex flex-col">
{props.children}
{price && (
<span
className={cn(
"text-[10px] font-medium",
isGoodPrice
? "text-emerald-500"
: "text-muted-foreground group-data-[selected]:text-primary-foreground/70",
)}
>
${price}
</span>
)}
</span>
</button>
);
}
export { Component };
Date picker Open page →
React App
Date pickerPick a date
Built with React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import { Label } from "@/components/ui/label";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { format } from "date-fns";
import { CalendarIcon } from "lucide-react";
import { useId, useState } from "react";
function Component() {
const id = useId();
const [date, setDate] = useState<Date | undefined>();
return (
<div>
<div className="space-y-2">
<Label htmlFor={id}>Date picker</Label>
<Popover>
<PopoverTrigger asChild>
<Button
id={id}
variant={"outline"}
className={cn(
"group w-full justify-between bg-background px-3 font-normal outline-offset-0 hover:bg-background focus-visible:border-ring focus-visible:outline-[3px] focus-visible:outline-ring/20",
!date && "text-muted-foreground",
)}
>
<span className={cn("truncate", !date && "text-muted-foreground")}>
{date ? format(date, "PPP") : "Pick a date"}
</span>
<CalendarIcon
size={16}
strokeWidth={2}
className="shrink-0 text-muted-foreground/80 transition-colors group-hover:text-foreground"
aria-hidden="true"
/>
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-2" align="start">
<Calendar mode="single" selected={date} onSelect={setDate} />
</PopoverContent>
</Popover>
</div>
<p className="mt-2 text-xs text-muted-foreground" role="region" aria-live="polite">
Built with{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Date range picker Open page →
React App
Date range pickerPick a date range
Built with React DayPicker
Usage.tsxComponent.tsx
Copy
"use client";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import { Label } from "@/components/ui/label";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { format } from "date-fns";
import { CalendarIcon } from "lucide-react";
import { useId, useState } from "react";
import { DateRange } from "react-day-picker";
function Component() {
const id = useId();
const [date, setDate] = useState<DateRange | undefined>();
return (
<div>
<div className="space-y-2">
<Label htmlFor={id}>Date range picker</Label>
<Popover>
<PopoverTrigger asChild>
<Button
id={id}
variant={"outline"}
className={cn(
"group w-full justify-between bg-background px-3 font-normal outline-offset-0 hover:bg-background focus-visible:border-ring focus-visible:outline-[3px] focus-visible:outline-ring/20",
!date && "text-muted-foreground",
)}
>
<span className={cn("truncate", !date && "text-muted-foreground")}>
{date?.from ? (
date.to ? (
<>
{format(date.from, "LLL dd, y")} - {format(date.to, "LLL dd, y")}
</>
) : (
format(date.from, "LLL dd, y")
)
) : (
"Pick a date range"
)}
</span>
<CalendarIcon
size={16}
strokeWidth={2}
className="shrink-0 text-muted-foreground/80 transition-colors group-hover:text-foreground"
aria-hidden="true"
/>
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-2" align="start">
<Calendar mode="range" selected={date} onSelect={setDate} />
</PopoverContent>
</Popover>
</div>
<p className="mt-2 text-xs text-muted-foreground" role="region" aria-live="polite">
Built with{" "}
<a
className="underline hover:text-foreground"
href="https://daypicker.dev/"
target="_blank"
rel="noopener nofollow"
>
React DayPicker
</a>
</p>
</div>
);
}
export { Component };
Dependencies
lucide-react react-day-picker date-fns
Source
Published
1/21/2025
Similar components
Apple Calendar Picker
124
Calendar
2
Calendar
31
Calendar With Presets
42
Dropdown Range Date Picker
49
Select
4
Tour
75
Calendar Date Picker
15
Assisted Password Confirmation
469
Breadcrumb
32
Integrations Grid
76
Animated Typewriter Text
48
Profile Card
174
Ruixen Moon Chat
554
Glass Card
183
SaaS Template
1.2k
Toast Notification
13
Avatar
82
Elegant Dark Pattern
201
Calendar input
11
Modern Login & Signup
508
FAQ roller
90
Footer section
1.0k
Price Target Fan
67
Loading more
Explore more
Part of Origin UI — browse the full library on 21st.dev.
Sidebar components95 Calendar components239 Date Picker components250 shadcn/ui components1043 Range Slider components101
Calendar [React Day Picker] | Community Components | 21st