Shadcn Calendar
React calendar for bookings, filters, and date ranges. Built with TypeScript and Tailwind CSS for Next.js using Base UI — single days, ranges, and locales.
The shadcn calendar is a month grid. Click a day and it selects — one date, several dates, or a from/to range. Use it inline on a booking page. Wrap it in a Popover when the trigger should be a field.
Looking for a neobrutalism version for shadcn?
Same calendar, thicker borders. The NeoBrutalism calendar is the kit if you want that look.
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"
/>
)mode="single" is one day. mode="range" is from/to. captionLayout="dropdown" jumps years.
Composition
CalendarDayButton is the cell. Override it through components.DayButton.
Persian / Hijri / Jalali Calendar
Swap the DayPicker import in components/ui/calendar.tsx. Official still writes react-day-picker/persian; v10 ships that as @daypicker/persian. The rest of the file stays.
- import { DayPicker } from "react-day-picker"
+ import { DayPicker } from "react-day-picker/persian"Basic
A single month. className="rounded-lg border" is the frame.
Range Calendar
mode="range" and numberOfMonths={2}. The fill is the span between from and to.
Month and Year Selector
captionLayout="dropdown" — month and year menus. Birthdays need this.
Presets
Buttons that set today, tomorrow, or in a week. Keep month in sync so the grid jumps with the preset.
Date and Time Picker
The grid picks the day. Native type="time" fields pick the clock.
Booked dates
Pass those days to disabled. Add a booked modifier if they should stay visible with a strike.
Custom Cell Size
--cell-size on the calendar. Override DayButton to drop a price under the number.
<Calendar
mode="single"
className="rounded-lg border [--cell-size:--spacing(11)] md:[--cell-size:--spacing(12)]"
/>Week Numbers
showWeekNumber adds a column on the start.
RTL
Wrap with DirectionProvider and dir="rtl". Pass a DayPicker locale so weekday names match.
import { arSA } from "react-day-picker/locale"
<Calendar mode="single" locale={arSA} dir="rtl" />API
These are react-day-picker props plus buttonVariant on the wrapper.
Prop
Type
CalendarDayButton
Prop
Type
className works on both. Pass a custom DayButton through components.
Keyboard
| Key | Action |
|---|---|
Arrow keys | Move between days |
Enter / Space | Select the focused day |
Page Up / Page Down | Previous / next month |
Shift + Page Up / Shift + Page Down | Previous / next year |
Home / End | First / last day of the week |
Notes
The 20th highlights the 19th
new Date("2025-06-01") is UTC midnight. West of UTC that is still May 31. Use new Date(2025, 5, 1), or set timeZone from Intl.DateTimeFormat().resolvedOptions().timeZone inside a useEffect so the server and the client agree.
Matcher functions run per day. An array of Dates is enough for a booked list.
With other components
Float next to a trigger
ButtonDay cells and nav
CardFrame around the month
FieldLabel on the picker
InputNative time next to day
Input GroupClock on the time field
Questions
Related
Was this page helpful?
Sign in to leave feedback.
Button Group
React button group for toolbars and split actions. Built with TypeScript and Tailwind CSS for Next.js using Base UI — fused borders, nested clusters, mixed inputs.
Card
React card for login forms, settings, and product tiles. Built with TypeScript and Tailwind CSS for Next.js using Base UI — header, content, footer, and an action slot.