shadcn.io is not affiliated with official shadcn/ui
Shadcn Date Picker for React and Tailwind
Input with a built-in calendar.
Installation
bunx --bun shadcn@latest add https://kit.dev/r/date-picker.jsonpnpm dlx shadcn@latest add https://kit.dev/r/date-picker.jsonnpx shadcn@latest add https://kit.dev/r/date-picker.jsonyarn shadcn@latest add https://kit.dev/r/date-picker.jsonThis component depends on Button, Calendar, Input and Input Group. Install them first if you haven't already.
Install the following dependencies:
bun add @ark-ui/react lucide-reactpnpm add @ark-ui/react lucide-reactnpm install @ark-ui/react lucide-reactyarn add @ark-ui/react lucide-reactCopy and paste the following code into your project.
"use client";
import {
DatePicker as ArkDatePicker,
useDatePickerContext,
} from "@ark-ui/react/date-picker";
import { Portal } from "@ark-ui/react/portal";
import { CalendarIcon, ClockIcon } from "lucide-react";
import type React from "react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import {
Calendar,
CalendarPresetTrigger,
} from "@/components/ui/calendar";
import type { Input, InputProps } from "@/components/ui/input";
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput,
} from "@/components/ui/input-group";
export const useDatePicker = useDatePickerContext;
export const DatePicker = (props: React.ComponentProps<typeof Calendar>) => {
const { positioning = { placement: "top" }, ...rest } = props;
return (
<Calendar
data-slot="date-picker"
inline={false}
positioning={positioning}
{...rest}
/>
);
};
export const DatePickerTrigger = (
props: React.ComponentProps<typeof ArkDatePicker.Trigger>
) => {
const { className, children, ...rest } = props;
return (
<ArkDatePicker.Control data-slot="date-picker-control">
<ArkDatePicker.Trigger
className={cn(
"justify-start",
"text-left data-placeholder-shown:[&>span]:text-muted-foreground",
"active:scale-100",
"[&_svg:not([class*='text-'])]:opacity-64",
className
)}
data-slot="date-picker-trigger"
{...rest}
>
{children}
</ArkDatePicker.Trigger>
</ArkDatePicker.Control>
);
};
interface DatePickerInputProps
extends Omit<React.ComponentProps<typeof ArkDatePicker.Input>, "size">,
InputProps {}
export const DatePickerInput = (props: DatePickerInputProps) => {
const { size, className, ...rest } = props;
return (
<ArkDatePicker.Control data-slot="date-picker-control">
<InputGroup size={size}>
<ArkDatePicker.Input asChild data-slot="date-picker-input" {...rest}>
<InputGroupInput />
</ArkDatePicker.Input>
<InputGroupAddon align="inline-end">
<InputGroupButton
asChild
data-slot="input-group-button"
size="icon-xs"
variant="ghost"
>
<ArkDatePicker.Trigger asChild data-slot="date-picker-trigger">
<Button size="icon-md" variant="ghost">
<CalendarIcon aria-hidden className="text-muted-foreground" />
</Button>
</ArkDatePicker.Trigger>
</InputGroupButton>
</InputGroupAddon>
</InputGroup>
</ArkDatePicker.Control>
);
};
export const DatePickerTimer = (props: React.ComponentProps<typeof Input>) => {
const { id, value, defaultValue, className, ...rest } = props;
return (
<InputGroup {...rest}>
<InputGroupAddon>
<ClockIcon />
</InputGroupAddon>
<InputGroupInput
className={cn(
"[&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none",
className
)}
defaultValue={defaultValue}
id={id}
step="1"
type="time"
value={value}
/>
</InputGroup>
);
};
export const DatePickerContent = (
props: React.ComponentProps<typeof ArkDatePicker.Content>
) => {
const { className, ...rest } = props;
return (
<Portal>
<ArkDatePicker.Positioner data-slot="date-picker-positioner">
<ArkDatePicker.Content
className={cn(
"[--cell-size:--spacing(8)]",
"z-[calc(50+var(--layer-index,0))]",
"w-fit min-w-72",
"p-3",
"bg-popover",
"text-popover-foreground",
"rounded-xl border shadow-lg/5",
"outline-none",
"origin-(--transform-origin)",
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
"data-[state=closed]:animate-out data-[state=open]:animate-in",
"data-[state=closed]:zoom-out-[98%] data-[state=open]:zoom-in-[98%]",
"motion-reduce:animate-none!",
className
)}
data-slot="date-picker-content"
{...rest}
/>
</ArkDatePicker.Positioner>
</Portal>
);
};
export const DatePickerValue = (
props: React.ComponentProps<typeof ArkDatePicker.ValueText>
) => {
const { className, ...rest } = props;
return (
<ArkDatePicker.ValueText
className={cn("font-medium text-sm", className)}
data-slot="date-picker-value"
{...rest}
/>
);
};
export const DatePickerPresetTrigger = (
props: React.ComponentProps<typeof ArkDatePicker.PresetTrigger>
) => (
<CalendarPresetTrigger data-slot="date-picker-preset-trigger" {...props} />
);Update the import paths to match your project setup.
Anatomy
DatePickerRoot
├── DatePickerClearTrigger
├── DatePickerContent
│ └── DatePickerPositioner
├── DatePickerLabel
├── DatePickerMonthSelect
├── DatePickerNextTrigger
├── DatePickerPresetTrigger
├── DatePickerPrevTrigger
├── DatePickerRangeText
├── DatePickerTable
│ ├── DatePickerTableBody
│ ├── DatePickerTableCell
│ │ └── DatePickerTableCellTrigger
│ ├── DatePickerTableHead
│ ├── DatePickerTableHeader
│ └── DatePickerTableRow
├── DatePickerView
│ ├── DatePickerViewControl
│ └── DatePickerViewTrigger
└── DatePickerYearSelectUsage
import { CalendarIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
CalendarMonthSelect,
CalendarNextTrigger,
CalendarPrevTrigger,
CalendarTable,
CalendarTableDays,
CalendarViewControl,
CalendarWeekDays,
CalendarYearSelect,
} from "@/components/ui/calendar";
import {
DatePicker,
DatePickerContent,
DatePickerTrigger,
DatePickerValue,
} from "@/components/ui/date-picker";<DatePicker>
<DatePickerTrigger asChild>
<Button className="min-w-56" variant="outline">
<CalendarIcon />
<DatePickerValue placeholder="Pick a date" />
</Button>
</DatePickerTrigger>
<DatePickerContent>
<CalendarViewControl>
<CalendarPrevTrigger />
<CalendarMonthSelect />
<CalendarYearSelect />
<CalendarNextTrigger />
</CalendarViewControl>
<CalendarTable>
<CalendarWeekDays />
<CalendarTableDays />
</CalendarTable>
</DatePickerContent>
</DatePicker>Accessibility
| Key | Description |
|---|---|
Enter | Activate the focused control. |
Space | Activate the focused control. |
Demos
Custom Format
Input
Range
Time
With Presets
API Reference
DatePicker
PropType
AttributeType
DatePickerContent
div
PropType
AttributeType
CSS variableType
DatePickerInput
div
PropType
AttributeType
DatePickerInput
input
PropType
AttributeType
DatePickerPositioner
div
PropType
AttributeType
CSS variableType
DatePickerPresetTrigger
button
PropType
AttributeType
DatePickerTrigger
button
PropType
AttributeType
DatePickerTimer
PropType
AttributeType
DatePickerValue
span
PropType
AttributeType
useDatePicker
PropType