A button that opens a calendar in a popover to choose a date or a range.
'use client'
import * as React from 'react'
import { DatePicker } from '@/components/ui/date-picker'
import { Label } from '@/components/ui/label'
export default function DatePickerDemo() {
const [date, setDate] = React.useState<Date | undefined>()
return (
<div className="grid gap-1.5">
<Label htmlFor="date-picker-demo">Appointment date</Label>
<DatePicker id="date-picker-demo" value={date} onValueChange={setDate} />
</div>
)
}
Built on Base UI
Installation
pnpm dlx shadcn@latest add https://kagadmodyaa.vercel.app/r/date-picker.jsonNeeds a React + Tailwind project set up with shadcn. Copies the component source straight into your project, so you can edit it.
Date Picker 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))
}
Built from Calendar, Popover and Button. The CLI installs them for you; if you copy manually, add calendar.tsx, popover.tsx and button.tsx to components/ui/ too.
Usage
import { DatePicker, DateRangePicker } from '@/components/ui/date-picker'
import { Label } from '@/components/ui/label'
const [date, setDate] = useState<Date | undefined>()
<Label htmlFor="when">Appointment date</Label>
<DatePicker id="when" value={date} onValueChange={setDate} />
// A range
<DateRangePicker value={range} onValueChange={setRange} />
// Options for the calendar inside
<DatePicker calendarProps={{ disabled: { before: new Date() } }} />Examples
Date range
'use client'
import * as React from 'react'
import type { DateRange } from 'react-day-picker'
import { DateRangePicker } from '@/components/ui/date-picker'
import { Label } from '@/components/ui/label'
export default function DatePickerRange() {
const [range, setRange] = React.useState<DateRange | undefined>()
return (
<div className="grid gap-1.5">
<Label htmlFor="date-picker-range">Stay</Label>
<DateRangePicker id="date-picker-range" value={range} onValueChange={setRange} />
</div>
)
}
API Reference
| Name | Type | Default | Description |
|---|---|---|---|
| value / onValueChange | Date | undefined / (date) => void | — | The picked date (controlled). For DateRangePicker the value is { from, to }. |
| defaultValue | Date | DateRange | — | The initially picked date or range (uncontrolled). |
| placeholder | string | 'Pick a date' / 'Pick a date range' | Text shown on the button while nothing is picked. |
| formatDate | (date: Date) => string | en-US, medium | Turns a date into the button text, e.g. (d) => d.toLocaleDateString("de-DE"). |
| calendarProps | CalendarProps | — | Passed to the Calendar: disabled, locale, weekStartsOn, numberOfMonths, captionLayout, … |
| disabled | boolean | false | Disables the button. |
| id / aria-label / className | string | — | Set on the trigger button, so a <Label htmlFor> can name it. |
| Closing | — | — | The popover closes when a date is picked (for a range, when the start and end days are). Escape closes it and returns focus to the button. |
| Keyboard | — | — | Opening the popover moves focus to the selected day (or today), so the arrow keys move straight away; Enter picks. |