Calendar
A date field component that allows users to enter and edit dates.
tsx
"use client"
import * as React from "react"import { Calendar } from "@/components/ui/calendar"
export function CalendarDemo() { const [date, setDate] = React.useState<Date | undefined>(new Date())
return ( <Calendar mode="single" selected={date} onSelect={setDate} className="rounded-md border shadow-sm" /> )}
Installation
CLI
bash
npx fivui add calendar
Manual
Install the following dependencies:
bash
npm install react-day-picker lucide-react
Copy and paste the following code into your project:
tsx
"use client"
import * as React from "react"import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon,} from "lucide-react"import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker"
import { cn } from "@/lib/utils"import { Button, buttonVariants } from "@/components/ui/button"
function Calendar({ className, classNames, showOutsideDays = true, captionLayout = "label", buttonVariant = "ghost", formatters, components, ...props}: React.ComponentProps<typeof DayPicker> & { buttonVariant?: React.ComponentProps<typeof Button>["variant"]}) { const defaultClassNames = getDefaultClassNames()
return ( <DayPicker showOutsideDays={showOutsideDays} className={cn( "bg-background group/calendar p-3 [--cell-size:--spacing(8)]", className )} captionLayout={captionLayout} formatters={{ formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }), ...formatters, }} classNames={{ root: cn("w-fit", defaultClassNames.root), months: cn( "flex gap-4 flex-col md:flex-row relative", defaultClassNames.months ), month: cn("flex flex-col w-full gap-4", defaultClassNames.month), nav: cn( "flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between", defaultClassNames.nav ), button_previous: cn( buttonVariants({ variant: buttonVariant }), "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none", defaultClassNames.button_previous ), button_next: cn( buttonVariants({ variant: buttonVariant }), "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none", defaultClassNames.button_next ), // ... more styling classes ...classNames, }} components={{ Root: ({ className, rootRef, ...props }) => ( <div data-slot="calendar" ref={rootRef} className={cn(className)} {...props} /> ), Chevron: ({ className, orientation, ...props }) => { if (orientation === "left") { return ( <ChevronLeftIcon className={cn("size-4", className)} {...props} /> ) } if (orientation === "right") { return ( <ChevronRightIcon className={cn("size-4", className)} {...props} /> ) } return ( <ChevronDownIcon className={cn("size-4", className)} {...props} /> ) }, DayButton: CalendarDayButton, ...components, }} {...props} /> )}
function CalendarDayButton({ className, day, modifiers, ...props}: React.ComponentProps<typeof DayButton>) { const defaultClassNames = getDefaultClassNames() const ref = React.useRef<HTMLButtonElement>(null) React.useEffect(() => { if (modifiers.focused) ref.current?.focus() }, [modifiers.focused])
return ( <Button ref={ref} variant="ghost" size="icon" className={cn( "data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground", defaultClassNames.day, className )} {...props} /> )}
export { Calendar, CalendarDayButton }
Usage
tsx
import { Calendar } from "@/components/ui/calendar"
tsx
const [date, setDate] = React.useState<Date | undefined>(new Date())
return ( <Calendar mode="single" selected={date} onSelect={setDate} className="rounded-lg border" />)
Examples
Range Selection
tsx
"use client"
import * as React from "react"import { Calendar } from "@/components/ui/calendar"
export function CalendarRangeDemo() { const [date, setDate] = React.useState<DateRange | undefined>({ from: new Date(2024, 0, 20), to: new Date(2024, 0, 25), })
return ( <Calendar mode="range" defaultMonth={date?.from} selected={date} onSelect={setDate} numberOfMonths={2} className="rounded-md border shadow-sm" /> )}
Multiple Selection
tsx
"use client"
import * as React from "react"import { Calendar } from "@/components/ui/calendar"
export function CalendarMultipleDemo() { const [dates, setDates] = React.useState<Date[] | undefined>([ new Date(2024, 0, 15), new Date(2024, 0, 20), new Date(2024, 0, 25), ])
return ( <Calendar mode="multiple" selected={dates} onSelect={setDates} className="rounded-md border shadow-sm" /> )}
Dropdown Navigation
Calendar with month and year dropdown selectors using captionLayout="dropdown".
tsx
"use client"
import * as React from "react"import { Calendar } from "@/components/ui/calendar"
export function CalendarWithDropdownsDemo() { const [date, setDate] = React.useState<Date | undefined>(new Date())
return ( <Calendar mode="single" selected={date} onSelect={setDate} captionLayout="dropdown" fromMonth={new Date(2020, 0)} toMonth={new Date(2030, 11)} className="rounded-md border shadow-sm" /> )}
Year Dropdown Only
Calendar with only year dropdown using captionLayout="dropdown-years".
tsx
"use client"
import * as React from "react"import { Calendar } from "@/components/ui/calendar"
export function CalendarWithCustomDropdownsDemo() { const [date, setDate] = React.useState<Date | undefined>(new Date())
return ( <Calendar mode="single" selected={date} onSelect={setDate} captionLayout="dropdown-years" fromMonth={new Date(2020, 0)} toMonth={new Date(2030, 11)} className="rounded-md border shadow-sm" /> )}
API Reference
Calendar
Prop | Type | Default | Description |
---|---|---|---|
mode | "single" | "multiple" | "range" | "single" | The selection mode of the calendar. |
selected | Date | Date[] | DateRange | - | The selected date(s). |
onSelect | function | - | Event handler called when the selection changes. |
defaultMonth | Date | - | The month to display by default. |
numberOfMonths | number | 1 | The number of months to display. |
showOutsideDays | boolean | true | Show days outside the current month. |
captionLayout | "label" | "dropdown" | "dropdown-years" | "label" | The layout of the month caption. |
disabled | Date | Date[] | function | - | Dates to disable. |
fromMonth | Date | - | Start month for navigation range. |
toMonth | Date | - | End month for navigation range. |
buttonVariant | ButtonVariant | "ghost" | Variant for navigation buttons. |