A month grid for picking a date or a range, fully keyboard navigable.

'use client'

import * as React from 'react'
import { Calendar } from '@/components/ui/calendar'

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

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

Installation

pnpm dlx shadcn@latest add https://kagadmodyaa.vercel.app/r/calendar.json

Needs a React + Tailwind project set up with shadcn. Copies the component source straight into your project, so you can edit it.

Calendar imports cn() from lib/utils.ts — add it too if you don't have it yet:

import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

Its navigation buttons use Button's styles. The CLI installs Button for you; if you copy manually, add components/ui/button.tsx too. Don't import react-day-picker's own stylesheet — Calendar is styled entirely with your theme tokens.

Usage

import { Calendar } from '@/components/ui/calendar'

const [date, setDate] = useState<Date | undefined>()

<Calendar mode="single" selected={date} onSelect={setDate} />

// A range
<Calendar mode="range" numberOfMonths={2} selected={range} onSelect={setRange} />

// Disable days
<Calendar mode="single" disabled={[{ dayOfWeek: [0, 6] }, { before: new Date() }]} />

Examples

Date range

'use client'

import * as React from 'react'
import type { DateRange } from 'react-day-picker'
import { Calendar } from '@/components/ui/calendar'

function daysFromToday(days: number) {
  const date = new Date()
  return new Date(date.getFullYear(), date.getMonth(), date.getDate() + days)
}

export default function CalendarRange() {
  const [range, setRange] = React.useState<DateRange | undefined>({ from: daysFromToday(1), to: daysFromToday(6) })

  return (
    <Calendar
      mode="range"
      numberOfMonths={2}
      selected={range}
      onSelect={setRange}
      className="rounded-lg border border-border"
    />
  )
}

Disabled days

'use client'

import * as React from 'react'
import { Calendar } from '@/components/ui/calendar'

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

  return (
    <Calendar
      mode="single"
      selected={date}
      onSelect={setDate}
      // No weekends, and nothing before today
      disabled={[{ dayOfWeek: [0, 6] }, { before: new Date() }]}
      className="rounded-lg border border-border"
    />
  )
}

API Reference

NameTypeDefaultDescription
mode'single' | 'multiple' | 'range'—What can be selected. Leave it out for a display-only calendar.
selected / onSelectDate | Date[] | DateRange | undefined / (selected) => void—The selection and its change handler; the shape depends on mode. A range is { from, to }.
requiredbooleanfalseStops the selection from being cleared by clicking the selected day again.
disabledMatcher | Matcher[]—Days that cannot be selected — a Date, { before }, { after }, { from, to }, { dayOfWeek: number[] } or a function.
defaultMonth / month / onMonthChangeDate / Date / (month: Date) => void—The month shown first, or control which month is shown.
numberOfMonthsnumber1How many months to show side by side (stacked on small screens).
showOutsideDaysbooleantrue for one month, false for severalShows the neighbouring months' days that fill the first and last weeks.
weekStartsOn0 | 1 | 2 | 3 | 4 | 5 | 6—First day of the week; 0 is Sunday. Follows the locale when unset.
localeLocale—A date-fns locale, e.g. import { fr } from 'react-day-picker/locale'. Translates month and day names and the accessible labels.
captionLayout'label' | 'dropdown' | 'dropdown-months' | 'dropdown-years''label'Swap the month caption for month and year dropdowns.
classNamesPartial<ClassNames>—Override the classes of any part, keyed by react-day-picker part names (day, month_caption, range_middle, …). Merged over the defaults.
Keyboard——Arrow keys move between days, PageUp and PageDown change month (with Shift, year), Home and End go to the start and end of the week, Enter or Space selects.