date picker
A date picker component with range and presets.
Philosophy
Date picking is a composition problem, not a component problem. A date picker is just a Calendar inside a Popover triggered by a Button - three components you already have. We document it as a pattern rather than shipping a dedicated component because the "right" date picker varies wildly by use case (single date, range, date-time, with presets).
How It's Built
Installation
The Date Picker is built using a composition of the <Popover /> and the <Calendar /> components.
See installation instructions for the Popover and the Calendar components.
Usage
"use client"
import * as React from "react"
import { ChevronDownIcon } from "lucide-react"
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"
export function DatePickerDemo() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(undefined)
return (
<div className="flex flex-col gap-3">
<Label className="px-1" htmlFor="date">
Date of birth
</Label>
<Popover onOpenChange={setOpen} open={open}>
<PopoverTrigger asChild>
<Button className="w-48 justify-between font-normal" id="date" variant="outline">
{date ? date.toLocaleDateString() : "Select date"}
<ChevronDownIcon aria-hidden="true" />
</Button>
</PopoverTrigger>
<PopoverContent side="top" align="start" className="w-auto p-0">
<Calendar
mode="single"
onSelect={(date) => {
setDate(date)
setOpen(false)
}}
selected={date}
/>
</PopoverContent>
</Popover>
</div>
)
}"use client"
import * as React from "react"
import { ChevronDownIcon } from "lucide-react"
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"
export function DatePickerDemo() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(undefined)
return (
<div className="flex flex-col gap-3">
<Label className="px-1" htmlFor="date">
Date of birth
</Label>
<Popover onOpenChange={setOpen} open={open}>
<PopoverTrigger asChild>
<Button className="w-48 justify-between font-normal" id="date" variant="outline">
{date ? date.toLocaleDateString() : "Select date"}
<ChevronDownIcon aria-hidden="true" />
</Button>
</PopoverTrigger>
<PopoverContent side="top" align="start" className="w-auto p-0">
<Calendar
mode="single"
onSelect={(date) => {
setDate(date)
setOpen(false)
}}
selected={date}
/>
</PopoverContent>
</Popover>
</div>
)
}See the @gentleduck/calendar documentation for more information on the headless calendar engine.
Examples
Date of Birth Picker
Picker with Input
Date and Time Picker
Natural Language Picker
This component uses the chrono-node library to parse natural language dates.
Date of Birth Picker (with dropdowns)
Date and Time Picker
Natural Language Picker
Form Integration
RTL Support
RTL is supported through the underlying Calendar and Popover components. Set dir="rtl" on the Calendar or use DirectionProvider at app/root level for global direction.
Motion
Motion components work standalone, but some compositions may behave unexpectedly — this is still under active development. If you find a broken composition, please file an issue.
Use MotionPopover, MotionPopoverContent, and MotionCalendar for animated date picking. The popover enters/exits with spring animation and the calendar has directional month transitions with staggered day cells.
Requires the motion package. Use MotionPopover instead of Popover, MotionPopoverContent instead of PopoverContent, and MotionCalendar instead of Calendar.