A component that lets users select and modify dates effortlessly.
@react-day-picker @lucide/reactSu | Mo | Tu | We | Th | Fr | Sa |
---|---|---|---|---|---|---|
1'use client'
2
3import * as React from 'react'
4
5import { Calendar } from '@/components/ui/calendar'
6
7export function CalendarDemo() {
8 const [date, setDate] = React.useState<Date | undefined>(new Date())
9
10 return (
11 <Calendar
12 mode="single"
13 selected={date}
14 onSelect={setDate}
15 captionLayout="dropdown"
16 />
17 )
18}
19
Install the following dependencies:
The Calendar
component leverages React DayPicker for its core functionality.
_
Refer to the React DayPicker docs for detailed guidance on customizing the Calendar
component.
_
The <Calendar>
component can be used to build a date picker. Learn more on the Date Picker .
_
Su | Mo | Tu | We | Th | Fr | Sa |
---|---|---|---|---|---|---|
Su | Mo | Tu | We | Th | Fr | Sa |
---|---|---|---|---|---|---|
1'use client'
2
3import * as React from 'react'
4import { type DateRange } from 'react-day-picker'
5
6import { Calendar } from '@/components/ui/calendar'
7
8export function Calendar02() {
9 const [date, setDate] = React.useState<DateRange | undefined>({
10 from: new Date(2025, 5, 9),
11 to: new Date(2025, 5, 26),
12 })
13
14 return (
15 <Calendar
16 mode="range"
17 defaultMonth={date?.from}
18 numberOfMonths={2}
19 selected={date}
20 onSelect={setDate}
21 />
22 )
23}
24
Su | Mo | Tu | We | Th | Fr | Sa |
---|---|---|---|---|---|---|
1'use client'
2
3import * as React from 'react'
4
5import { Calendar } from '@/components/ui/calendar'
6import { Label } from '@/components/ui/label'
7import {
8 Select,
9 SelectContent,
10 SelectItem,
11 SelectTrigger,
12 SelectValue,
13} from '@/components/ui/select'
14
15export function Calendar13() {
16 const [dropdown, setDropdown] =
17 React.useState<React.ComponentProps<typeof Calendar>['captionLayout']>(
18 'dropdown',
19 )
20 const [date, setDate] = React.useState<Date | undefined>(
21 new Date(2025, 5, 12),
22 )
23
24 return (
25 <div className="flex flex-col gap-4">
26 <Calendar
27 mode="single"
28 defaultMonth={date}
29 selected={date}
30 onSelect={setDate}
31 captionLayout={dropdown}
32 />
33 <div className="flex flex-col gap-3">
34 <Label htmlFor="dropdown" className="px-1">
35 Dropdown
36 </Label>
37 <Select
38 value={dropdown}
39 onValueChange={(value) =>
40 setDropdown(
41 value as React.ComponentProps<
42 typeof Calendar
43 >['captionLayout'],
44 )
45 }
46 >
47 <SelectTrigger
48 id="dropdown"
49 size="sm"
50 className="bg-background w-full"
51 >
52 <SelectValue placeholder="Dropdown" />
53 </SelectTrigger>
54 <SelectContent align="center">
55 <SelectItem value="dropdown">Month and Year</SelectItem>
56 <SelectItem value="dropdown-months">
57 Month Only
58 </SelectItem>
59 <SelectItem value="dropdown-years">
60 Year Only
61 </SelectItem>
62 </SelectContent>
63 </Select>
64 </div>
65 </div>
66 )
67}
68
1'use client'
2
3import * as React from 'react'
4import { ChevronDownIcon } from 'lucide-react'
5
6import { Button } from '@/components/ui/button'
7import { Calendar } from '@/components/ui/calendar'
8import { Label } from '@/components/ui/label'
9import {
10 Popover,
11 PopoverContent,
12 PopoverTrigger,
13} from '@/components/ui/popover'
14
15export function Calendar22() {
16 const [open, setOpen] = React.useState(false)
17 const [date, setDate] = React.useState<Date | undefined>(undefined)
18
19 return (
20 <div className="flex flex-col gap-3">
21 <Label htmlFor="date" className="px-1">
22 Date of birth
23 </Label>
24 <Popover open={open} onOpenChange={setOpen}>
25 <PopoverTrigger asChild>
26 <Button
27 variant="outline"
28 id="date"
29 className="text-primary border-border h-10 w-48 justify-between font-medium hover:bg-gray-100"
30 >
31 {date ? date.toLocaleDateString() : 'Select date'}
32 <ChevronDownIcon />
33 </Button>
34 </PopoverTrigger>
35 <PopoverContent
36 className="w-auto overflow-hidden p-0"
37 align="start"
38 >
39 <Calendar
40 mode="single"
41 selected={date}
42 className="border-0 shadow-none"
43 captionLayout="dropdown"
44 onSelect={(date) => {
45 setDate(date)
46 setOpen(false)
47 }}
48 />
49 </PopoverContent>
50 </Popover>
51 </div>
52 )
53}
54
1'use client'
2
3import * as React from 'react'
4import { ChevronDownIcon } from 'lucide-react'
5
6import { Button } from '@/components/ui/button'
7import { Calendar } from '@/components/ui/calendar'
8import { Input } from '@/components/ui/input'
9import { Label } from '@/components/ui/label'
10import {
11 Popover,
12 PopoverContent,
13 PopoverTrigger,
14} from '@/components/ui/popover'
15
16export function Calendar24() {
17 const [open, setOpen] = React.useState(false)
18 const [date, setDate] = React.useState<Date | undefined>(undefined)
19
20 return (
21 <div className="flex gap-4">
22 <div className="flex flex-col gap-3">
23 <Label htmlFor="date-picker" className="px-1">
24 Date
25 </Label>
26 <Popover open={open} onOpenChange={setOpen}>
27 <PopoverTrigger asChild>
28 <Button
29 variant="outline"
30 id="date-picker"
31 className="text-primary border-border h-10 w-32 justify-between font-medium hover:bg-gray-100"
32 >
33 {date ? date.toLocaleDateString() : 'Select date'}
34 <ChevronDownIcon />
35 </Button>
36 </PopoverTrigger>
37 <PopoverContent
38 className="w-auto overflow-hidden p-0"
39 align="start"
40 >
41 <Calendar
42 mode="single"
43 selected={date}
44 className="border-0 shadow-none"
45 captionLayout="dropdown"
46 onSelect={(date) => {
47 setDate(date)
48 setOpen(false)
49 }}
50 />
51 </PopoverContent>
52 </Popover>
53 </div>
54 <div className="flex flex-col gap-3">
55 <Label htmlFor="time-picker" className="px-1">
56 Time
57 </Label>
58 <Input
59 type="time"
60 id="time-picker"
61 step="1"
62 defaultValue="05:15:10"
63 className="bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
64 />
65 </div>
66 </div>
67 )
68}
69
This component relies on the chrono-node
library for parsing dates from natural language text.
1'use client'
2
3import * as React from 'react'
4import { parseDate } from 'chrono-node'
5import { CalendarIcon } from 'lucide-react'
6
7import { Button } from '@/components/ui/button'
8import { Calendar } from '@/components/ui/calendar'
9import { Input } from '@/components/ui/input'
10import { Label } from '@/components/ui/label'
11import {
12 Popover,
13 PopoverContent,
14 PopoverTrigger,
15} from '@/components/ui/popover'
16
17function formatDate(date: Date | undefined) {
18 if (!date) {
19 return ''
20 }
21
22 return date.toLocaleDateString('en-US', {
23 day: '2-digit',
24 month: 'long',
25 year: 'numeric',
26 })
27}
28
29export function Calendar29() {
30 const [open, setOpen] = React.useState(false)
31 const [value, setValue] = React.useState('In 5 days')
32 const [date, setDate] = React.useState<Date | undefined>(
33 parseDate(value) || undefined,
34 )
35 const [month, setMonth] = React.useState<Date | undefined>(date)
36
37 return (
38 <div className="flex flex-col gap-3">
39 <Label htmlFor="date" className="px-1">
40 Schedule Date
41 </Label>
42 <div className="relative flex gap-2">
43 <Input
44 id="date"
45 value={value}
46 placeholder="Tomorrow or next week"
47 onChange={(e) => {
48 setValue(e.target.value)
49 const date = parseDate(e.target.value)
50 if (date) {
51 setDate(date)
52 setMonth(date)
53 }
54 }}
55 onKeyDown={(e) => {
56 if (e.key === 'ArrowDown') {
57 e.preventDefault()
58 setOpen(true)
59 }
60 }}
61 />
62 <Popover open={open} onOpenChange={setOpen}>
63 <PopoverTrigger asChild>
64 <Button
65 id="date-picker"
66 variant="ghost"
67 className="absolute top-1/2 right-2 size-6 -translate-y-1/2"
68 >
69 <CalendarIcon className="size-3.5" />
70 <span className="sr-only">Select date</span>
71 </Button>
72 </PopoverTrigger>
73 <PopoverContent
74 className="w-auto overflow-hidden p-0"
75 align="end"
76 >
77 <Calendar
78 mode="single"
79 selected={date}
80 captionLayout="dropdown"
81 month={month}
82 className="border-0 shadow-none"
83 onMonthChange={setMonth}
84 onSelect={(date) => {
85 setDate(date)
86 setValue(formatDate(date))
87 setOpen(false)
88 }}
89 />
90 </PopoverContent>
91 </Popover>
92 </div>
93 <div className="text-muted-foreground px-1 text-sm">
94 Your post will be published on{' '}
95 <span className="font-medium">{formatDate(date)}</span>.
96 </div>
97 </div>
98 )
99}
100
The Calendar
component is based on react-day-picker
and supports all of its props. And adds:
Prop | Type | Default |
---|---|---|
showOutsideDays | boolean | true |
captionLayout | label , dropdown | label |
buttonVariant | primary , secondary , outline , error , success , ghost ,link | ghost |
formatters | Partial<DayPickerFormatters> | - |
components | Partial<DayPickerComponents> | - |