Components
- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Data Table
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input Group
- Input OTP
- Item
- Kbd
- Label
- Menubar
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Tooltip
- Typography
Get Started
"use client"
import * as React from "react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
import { format } from "date-fns"
import { ChevronDownIcon } from "lucide-react"
export function DatePickerDemo() {
const [date, setDate] = React.useState<Date>()
return (
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
data-empty={!date}
className="data-[empty=true]:text-muted-foreground w-[212px] justify-between text-left font-normal"
>
{date ? format(date, "PPP") : <span>Pick a date</span>}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
defaultMonth={date}
/>
</PopoverContent>
</Popover>
)
}
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 { format } from "date-fns"
import { Calendar as CalendarIcon } from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function DatePickerDemo() {
const [date, setDate] = React.useState<Date>()
return (
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
data-empty={!date}
className="data-[empty=true]:text-muted-foreground w-[280px] justify-start text-left font-normal"
>
<CalendarIcon />
{date ? format(date, "PPP") : <span>Pick a date</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar mode="single" selected={date} onSelect={setDate} />
</PopoverContent>
</Popover>
)
}See the React DayPicker documentation for more information.
Examples
Basic
A basic date picker component.
"use client"
import * as React from "react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Field, FieldLabel } from "@/components/ui/field"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
import { format } from "date-fns"
export function DatePickerSimple() {
const [date, setDate] = React.useState<Date>()
return (
<Field className="mx-auto w-44">
<FieldLabel htmlFor="date-picker-simple">Date</FieldLabel>
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date-picker-simple"
className="justify-start font-normal"
>
{date ? format(date, "PPP") : <span>Pick a date</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
defaultMonth={date}
/>
</PopoverContent>
</Popover>
</Field>
)
}
Range Picker
A date picker component for selecting a range of dates.
"use client"
import * as React from "react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Field, FieldLabel } from "@/components/ui/field"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
import { addDays, format } from "date-fns"
import { CalendarIcon } from "lucide-react"
import { type DateRange } from "react-day-picker"
export function DatePickerWithRange() {
const [date, setDate] = React.useState<DateRange | undefined>({
from: new Date(new Date().getFullYear(), 0, 20),
to: addDays(new Date(new Date().getFullYear(), 0, 20), 20),
})
return (
<Field className="mx-auto w-60">
<FieldLabel htmlFor="date-picker-range">Date Picker Range</FieldLabel>
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date-picker-range"
className="justify-start px-2.5 font-normal"
>
<CalendarIcon />
{date?.from ? (
date.to ? (
<>
{format(date.from, "LLL dd, y")} -{" "}
{format(date.to, "LLL dd, y")}
</>
) : (
format(date.from, "LLL dd, y")
)
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="range"
defaultMonth={date?.from}
selected={date}
onSelect={setDate}
numberOfMonths={2}
/>
</PopoverContent>
</Popover>
</Field>
)
}
Date of Birth
A date picker component for selecting a date of birth. This component includes a dropdown caption layout for date and month selection.
"use client"
import * as React from "react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Field, FieldLabel } from "@/components/ui/field"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function DatePickerSimple() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(undefined)
return (
<Field className="mx-auto w-44">
<FieldLabel htmlFor="date">Date of birth</FieldLabel>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date"
className="justify-start font-normal"
>
{date ? date.toLocaleDateString() : "Select date"}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
<Calendar
mode="single"
selected={date}
defaultMonth={date}
captionLayout="dropdown"
onSelect={(date) => {
setDate(date)
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</Field>
)
}
Input
A date picker component with an input field for selecting a date.
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
import { Field, FieldLabel } from "@/components/ui/field"
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput,
} from "@/components/ui/input-group"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
import { CalendarIcon } from "lucide-react"
function formatDate(date: Date | undefined) {
if (!date) {
return ""
}
return date.toLocaleDateString("en-US", {
day: "2-digit",
month: "long",
year: "numeric",
})
}
function isValidDate(date: Date | undefined) {
if (!date) {
return false
}
return !isNaN(date.getTime())
}
export function DatePickerInput() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(
new Date("2025-06-01")
)
const [month, setMonth] = React.useState<Date | undefined>(date)
const [value, setValue] = React.useState(formatDate(date))
return (
<Field className="mx-auto w-48">
<FieldLabel htmlFor="date-required">Subscription Date</FieldLabel>
<InputGroup>
<InputGroupInput
id="date-required"
value={value}
placeholder="June 01, 2025"
onChange={(e) => {
const date = new Date(e.target.value)
setValue(e.target.value)
if (isValidDate(date)) {
setDate(date)
setMonth(date)
}
}}
onKeyDown={(e) => {
if (e.key === "ArrowDown") {
e.preventDefault()
setOpen(true)
}
}}
/>
<InputGroupAddon align="inline-end">
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<InputGroupButton
id="date-picker"
variant="ghost"
size="icon-xs"
aria-label="Select date"
>
<CalendarIcon />
<span className="sr-only">Select date</span>
</InputGroupButton>
</PopoverTrigger>
<PopoverContent
className="w-auto overflow-hidden p-0"
align="end"
alignOffset={-8}
sideOffset={10}
>
<Calendar
mode="single"
selected={date}
month={month}
onMonthChange={setMonth}
onSelect={(date) => {
setDate(date)
setValue(formatDate(date))
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</InputGroupAddon>
</InputGroup>
</Field>
)
}
Time Picker
A date picker component with a time input field for selecting a time.
"use client"
import * as React from "react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
import { format } from "date-fns"
import { ChevronDownIcon } from "lucide-react"
export function DatePickerTime() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(undefined)
return (
<FieldGroup className="mx-auto max-w-xs flex-row">
<Field>
<FieldLabel htmlFor="date-picker-optional">Date</FieldLabel>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date-picker-optional"
className="w-32 justify-between font-normal"
>
{date ? format(date, "PPP") : "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
defaultMonth={date}
onSelect={(date) => {
setDate(date)
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</Field>
<Field className="w-32">
<FieldLabel htmlFor="time-picker-optional">Time</FieldLabel>
<Input
type="time"
id="time-picker-optional"
step="1"
defaultValue="10:30:00"
className="bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</Field>
</FieldGroup>
)
}
Natural Language Picker
This component uses the chrono-node library to parse natural language dates.
Your post will be published on January 22, 2026.
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
import { Field, FieldLabel } from "@/components/ui/field"
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput,
} from "@/components/ui/input-group"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
import { parseDate } from "chrono-node"
import { CalendarIcon } from "lucide-react"
function formatDate(date: Date | undefined) {
if (!date) {
return ""
}
return date.toLocaleDateString("en-US", {
day: "2-digit",
month: "long",
year: "numeric",
})
}
export function DatePickerNaturalLanguage() {
const [open, setOpen] = React.useState(false)
const [value, setValue] = React.useState("In 2 days")
const [date, setDate] = React.useState<Date | undefined>(
parseDate(value) || undefined
)
return (
<Field className="mx-auto max-w-xs">
<FieldLabel htmlFor="date-optional">Schedule Date</FieldLabel>
<InputGroup>
<InputGroupInput
id="date-optional"
value={value}
placeholder="Tomorrow or next week"
onChange={(e) => {
setValue(e.target.value)
const date = parseDate(e.target.value)
if (date) {
setDate(date)
}
}}
onKeyDown={(e) => {
if (e.key === "ArrowDown") {
e.preventDefault()
setOpen(true)
}
}}
/>
<InputGroupAddon align="inline-end">
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<InputGroupButton
id="date-picker"
variant="ghost"
size="icon-xs"
aria-label="Select date"
>
<CalendarIcon />
<span className="sr-only">Select date</span>
</InputGroupButton>
</PopoverTrigger>
<PopoverContent
className="w-auto overflow-hidden p-0"
align="end"
sideOffset={8}
>
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
defaultMonth={date}
onSelect={(date) => {
setDate(date)
setValue(formatDate(date))
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</InputGroupAddon>
</InputGroup>
<div className="text-muted-foreground px-1 text-sm">
Your post will be published on{" "}
<span className="font-medium">{formatDate(date)}</span>.
</div>
</Field>
)
}
Deploy your shadcn/ui app on Vercel
Trusted by OpenAI, Sonos, Adobe, and more.
Vercel provides tools and infrastructure to deploy apps and features at scale.
Deploy to Vercel