Components

Calendar

A date field component that allows users to enter and edit dates.

September 2026

Installation

Cortexcn
pnpm dlx shadcn@latest add @cortexcn/calendar

Usage

import { Calendar, CalendarDayButton } from "@/components/calendar";

Examples

Single

September 2026
import * as React from "react"import { Calendar } from "@/components/calendar"import { Card, CardContent } from "@/components/card"export function CalendarSingle() {  const [date, setDate] = React.useState<Date | undefined>(    new Date(new Date().getFullYear(), new Date().getMonth(), 12)  )  return (    <div className="flex flex-col gap-6">      <Card className="mx-auto w-fit p-0">        <CardContent className="p-0">          <Calendar            mode="single"            selected={date}            onSelect={setDate}            captionLayout="dropdown"          />        </CardContent>      </Card>    </div>  )}

Multiple

September 2026
import { Calendar } from "@/components/calendar"import { Card, CardContent } from "@/components/card"export function CalendarMultiple() {  return (    <div className="flex flex-col gap-6">      <Card className="mx-auto w-fit p-0">        <CardContent className="p-0">          <Calendar mode="multiple" />        </CardContent>      </Card>    </div>  )}

Week numbers

February 2026
06
07
08
09
import * as React from "react"import { Calendar } from "@/components/calendar"import { Card, CardContent } from "@/components/card"export function CalendarWeekNumbers() {  const [date, setDate] = React.useState<Date | undefined>(    new Date(new Date().getFullYear(), 1, 3)  )  return (    <div className="flex flex-col gap-6 justify-center">      <Card className="mx-auto w-fit p-0">        <CardContent className="p-0">          <Calendar            mode="single"            defaultMonth={date}            selected={date}            onSelect={setDate}            showWeekNumber          />        </CardContent>      </Card>    </div>  )}

Booked dates

February 2026
import * as React from "react"import { Calendar } from "@/components/calendar"import { Card, CardContent } from "@/components/card"export function CalendarBookedDates() {  const [date, setDate] = React.useState<Date | undefined>(    new Date(new Date().getFullYear(), 1, 3)  )  const bookedDates = Array.from(    { length: 15 },    (_, i) => new Date(new Date().getFullYear(), 1, 12 + i)  )  return (    <div className="flex flex-col gap-6">      <Card className="mx-auto w-fit p-0">        <CardContent className="p-0">          <Calendar            mode="single"            defaultMonth={date}            selected={date}            onSelect={setDate}            disabled={bookedDates}            modifiers={{              booked: bookedDates,            }}            modifiersClassNames={{              booked: "[&>button]:line-through opacity-100",            }}          />        </CardContent>      </Card>    </div>  )}

Range

January 2026
February 2026
import * as React from "react"import { addDays } from "date-fns"import { type DateRange } from "react-day-picker"import { Calendar } from "@/components/calendar"import { Card, CardContent } from "@/components/card"export function CalendarRange() {  const [dateRange, setDateRange] = React.useState<DateRange | undefined>({    from: new Date(new Date().getFullYear(), 0, 12),    to: addDays(new Date(new Date().getFullYear(), 0, 12), 30),  })  return (    <div className="flex flex-col gap-6 p-12">      <Card className="mx-auto w-fit p-0">        <CardContent className="p-0">          <Calendar            mode="range"            defaultMonth={dateRange?.from}            selected={dateRange}            onSelect={setDateRange}            numberOfMonths={2}            disabled={(date) =>              date > new Date() || date < new Date("1900-01-01")            }          />        </CardContent>      </Card>    </div>  )}

Range multiple months

abril 2026
mayo 2026
junio 2026
import * as React from "react"import { addDays } from "date-fns"import { type DateRange } from "react-day-picker"import { es } from "react-day-picker/locale"import { Calendar } from "@/components/calendar"import { Card, CardContent } from "@/components/card"export function CalendarRangeMultipleMonths() {  const [range, setRange] = React.useState<DateRange | undefined>({    from: new Date(new Date().getFullYear(), 3, 12),    to: addDays(new Date(new Date().getFullYear(), 3, 12), 60),  })  return (    <div className="flex flex-col gap-6 p-12">      <Card className="mx-auto w-fit p-0">        <CardContent className="p-0">          <Calendar            mode="range"            defaultMonth={range?.from}            selected={range}            onSelect={setRange}            numberOfMonths={3}            locale={es}            fixedWeeks          />        </CardContent>      </Card>    </div>  )}

With time

September 2026
import * as React from "react"import { Calendar } from "@/components/calendar"import { Card, CardContent, CardFooter } from "@/components/card"import { Field, FieldGroup, FieldLabel } from "@/components/field"import { InputGroup, InputGroupAddon, InputGroupInput } from "@/components/input-group"import { Clock2Icon } from "lucide-react"export function CalendarWithTime() {  const [date, setDate] = React.useState<Date | undefined>(    new Date(new Date().getFullYear(), new Date().getMonth(), 12)  )  return (    <div className="flex flex-col gap-6">      <Card size="sm" className="mx-auto w-fit">        <CardContent>          <Calendar            mode="single"            selected={date}            onSelect={setDate}            className="p-0"          />        </CardContent>        <CardFooter className="border-t bg-card">          <FieldGroup>            <Field>              <FieldLabel htmlFor="time-from">Start Time</FieldLabel>              <InputGroup>                <InputGroupInput                  id="time-from"                  type="time"                  step="1"                  defaultValue="10:30:00"                  className="appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"                />                <InputGroupAddon>                  <Clock2Icon className="text-muted-foreground" />                </InputGroupAddon>              </InputGroup>            </Field>            <Field>              <FieldLabel htmlFor="time-to">End Time</FieldLabel>              <InputGroup>                <InputGroupInput                  id="time-to"                  type="time"                  step="1"                  defaultValue="12:30:00"                  className="appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"                />                <InputGroupAddon>                  <Clock2Icon className="text-muted-foreground" />                </InputGroupAddon>              </InputGroup>            </Field>          </FieldGroup>        </CardFooter>      </Card>    </div>  )}

With presets

September 2026
import * as React from "react"import { addDays } from "date-fns"import { Button } from "@/components/button"import { Calendar } from "@/components/calendar"import { Card, CardContent, CardFooter } from "@/components/card"export function CalendarWithPresets() {  const [date, setDate] = React.useState<Date | undefined>(    new Date(new Date().getFullYear(), 1, 12)  )  const [currentMonth, setCurrentMonth] = React.useState<Date>(    new Date(new Date().getFullYear(), new Date().getMonth(), 1)  )  return (    <div className="flex flex-col gap-6">      <Card className="mx-auto w-fit max-w-[300px]" size="sm">        <CardContent className="px-4">          <Calendar            mode="single"            selected={date}            onSelect={setDate}            month={currentMonth}            onMonthChange={setCurrentMonth}            fixedWeeks            className="p-0 [--cell-size:--spacing(9.5)]"          />        </CardContent>        <CardFooter className="flex flex-wrap gap-2 border-t">          {[            { label: "Today", value: 0 },            { label: "Tomorrow", value: 1 },            { label: "In 3 days", value: 3 },            { label: "In a week", value: 7 },            { label: "In 2 weeks", value: 14 },          ].map((preset) => (            <Button              key={preset.value}              variant="outline"              size="sm"              className="flex-1"              onClick={() => {                const newDate = addDays(new Date(), preset.value)                setDate(newDate)                setCurrentMonth(                  new Date(newDate.getFullYear(), newDate.getMonth(), 1)                )              }}            >              {preset.label}            </Button>          ))}        </CardFooter>      </Card>    </div>  )}

Custom days

December 2026
import * as React from "react"import { addDays } from "date-fns"import { type DateRange } from "react-day-picker"import { Calendar, CalendarDayButton } from "@/components/calendar"import { Card, CardContent } from "@/components/card"export function CalendarCustomDays() {  const [range, setRange] = React.useState<DateRange | undefined>({    from: new Date(new Date().getFullYear(), 11, 8),    to: addDays(new Date(new Date().getFullYear(), 11, 8), 10),  })  return (    <div className="flex flex-col gap-6">      <Card className="mx-auto w-fit p-0">        <CardContent className="p-0">          <Calendar            mode="range"            defaultMonth={range?.from}            selected={range}            onSelect={setRange}            numberOfMonths={1}            captionLayout="dropdown"            className="[--cell-size:--spacing(10)] md:[--cell-size:--spacing(12)]"            formatters={{              formatMonthDropdown: (date) => {                return date.toLocaleString("default", { month: "long" })              },            }}            components={{              DayButton: ({ children, modifiers, day, ...props }) => {                const isWeekend =                  day.date.getDay() === 0 || day.date.getDay() === 6                return (                  <CalendarDayButton day={day} modifiers={modifiers} {...props}>                    {children}                    {!modifiers.outside && (                      <span>{isWeekend ? "$120" : "$100"}</span>                    )}                  </CalendarDayButton>                )              },            }}          />        </CardContent>      </Card>    </div>  )}

Date picker simple

import * as React from "react"import { format } from "date-fns"import { Button } from "@/components/button"import { Calendar } from "@/components/calendar"import { Field, FieldLabel } from "@/components/field"import { Popover, PopoverContent, PopoverTrigger } from "@/components/popover"import { CalendarIcon } from "lucide-react"export function DatePickerSimple() {  const [date, setDate] = React.useState<Date>()  return (    <div className="flex flex-col gap-6">      <Field className="mx-auto w-72">        <FieldLabel htmlFor="date-picker-simple">Date</FieldLabel>        <Popover>          <PopoverTrigger asChild>            <Button              variant="outline"              id="date-picker-simple"              className="justify-start px-2.5 font-normal"            >              <CalendarIcon data-icon="inline-start" />              {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} />          </PopoverContent>        </Popover>      </Field>    </div>  )}

Date picker with dropdowns

import * as React from "react"import { format } from "date-fns"import { Button } from "@/components/button"import { Calendar } from "@/components/calendar"import { Field, FieldLabel } from "@/components/field"import { Popover, PopoverContent, PopoverTrigger } from "@/components/popover"import { ChevronDownIcon } from "lucide-react"export function DataPickerWithDropdowns() {  const [date, setDate] = React.useState<Date>()  const [open, setOpen] = React.useState(false)  return (    <div className="flex flex-col gap-6">      <Field className="mx-auto w-72">        <Popover open={open} onOpenChange={setOpen}>          <FieldLabel htmlFor="date-picker-with-dropdowns-desktop">            Date          </FieldLabel>          <PopoverTrigger asChild>            <Button              variant="outline"              id="date-picker-with-dropdowns-desktop"              className="justify-start px-2.5 font-normal"            >              {date ? format(date, "PPP") : <span>Pick a date</span>}              <ChevronDownIcon data-icon="inline-start" className="ml-auto" />            </Button>          </PopoverTrigger>          <PopoverContent className="w-auto p-0" align="start">            <Calendar              mode="single"              selected={date}              onSelect={setDate}              captionLayout="dropdown"            />            <div className="flex gap-2 border-t p-2">              <Button                variant="outline"                size="sm"                className="w-full"                onClick={() => setOpen(false)}              >                Done              </Button>            </div>          </PopoverContent>        </Popover>      </Field>    </div>  )}

Date picker range

import * as React from "react"import { addDays, format } from "date-fns"import { type DateRange } from "react-day-picker"import { Button } from "@/components/button"import { Calendar } from "@/components/calendar"import { Field, FieldLabel } from "@/components/field"import { Popover, PopoverContent, PopoverTrigger } from "@/components/popover"import { CalendarIcon } from "lucide-react"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 (    <div className="flex flex-col gap-6">      <Field className="mx-auto w-72">        <FieldLabel htmlFor="date-picker-range">Date Picker Range</FieldLabel>        <Popover>          <PopoverTrigger asChild>            <Button              id="date-picker-range"              variant="outline"              className="justify-start px-2.5 font-normal"            >              <CalendarIcon data-icon="inline-start" />              {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>    </div>  )}

In card

September 2026
import { Calendar } from "@/components/calendar"import { Card, CardContent } from "@/components/card"export function CalendarInCard() {  return (    <div className="flex flex-col gap-6">      <Card className="mx-auto w-fit p-0">        <CardContent className="p-0">          <Calendar mode="single" />        </CardContent>      </Card>    </div>  )}

In popover

import { Button } from "@/components/button"import { Calendar } from "@/components/calendar"import { Popover, PopoverContent, PopoverTrigger } from "@/components/popover"import { CalendarIcon } from "lucide-react"export function CalendarInPopover() {  return (    <div className="flex flex-col gap-6">      <Popover>        <PopoverTrigger asChild>          <Button variant="outline" className="px-2.5 font-normal">            <CalendarIcon data-icon="inline-start" />            Open Calendar          </Button>        </PopoverTrigger>        <PopoverContent className="w-auto p-0" align="start">          <Calendar mode="single" />        </PopoverContent>      </Popover>    </div>  )}

Adapted from the shadcn/ui Calendar (MIT).