Date Picker

Month-grid calendar with a selection pill that glides between days, directional month slides, single, range, week or multiple-day selection across one or several side-by-side months, ISO week numbers, per-day labels, min/max and per-day disabling, full keyboard grid navigation, a date field, a two-month range field with presets, a booking calendar with nightly prices, time and date-time wheels and a month picker. Locale-aware, reduced-motion safe.

Date Picker

date-picker.tsx

Date field whose calendar morphs open from the trigger corner and closes on pick.

Date Picker Date Picker preview width

Install

$ bunx --bun shadcn add @karaui/date-picker
@karaui not found? Add it to components.json
{
  "registries": {
    "@karaui": "https://karaui.kamisama-v0.my.id/r/{name}.json"
  }
}

@karaui is in shadcn's public registry directory, so the latest CLI needs no setup. On an older CLI, merge this into the existing file once and every @karaui/… install resolves.

API Reference

value?
Date | null
—
defaultValue?
Date | null
null
onValueChange?
((date: Date) => void)
—
placeholder?
string
Pick a date
formatOptions?
DateTimeFormatOptions

Intl options for the trigger label. Default: medium date.

{ dateStyle: "medium" }
locale?
string

Default "en-US".

en-US
minDate?
Date
—
maxDate?
Date
—
isDateDisabled?
((date: Date) => boolean)
—
weekStartsOn?
0 | 1 | 2 | 3 | 4 | 5 | 6
—
align?
"end" | "start"
start
disabled?
boolean
—
className?
string
—
aria-label?
string
Choose date

Calendar

calendar.tsx

Inline single-date calendar; the selected pill glides between days. Weekends disabled in this demo.

Date Picker Calendar preview width

Install

$ bunx --bun shadcn add @karaui/calendar

API Reference

minDate?
Date

Earliest selectable day (inclusive).

—
maxDate?
Date

Latest selectable day (inclusive).

—
isDateDisabled?
((date: Date) => boolean)

Extra per-day rule, e.g. weekends or booked dates.

—
weekStartsOn?
0 | 1 | 2 | 3 | 4 | 5 | 6

0 = Sunday … 6 = Saturday. Default 0.

—
locale?
string

BCP 47 locale for month, weekday and day labels. Default "en-US" — a fixed default keeps server and client output identical for hydration.

—
month?
Date

Controlled visible month (any day inside it).

—
defaultMonth?
Date

Uncontrolled initial visible month. Default: the selection or today.

—
onMonthChange?
((month: Date) => void)
—
numberOfMonths?
number

Months shown side by side (stacked below `sm`). Default 1. With more than one, days outside each month are left blank so none repeats.

—
showWeekNumber?
boolean

Adds an ISO 8601 week-number column ("Wk") before each row.

—
getDayMeta?
((date: Date) => CalendarDayMeta | null)

Per-day label, tone and blocking, e.g. nightly prices or booked days. Passing it switches the grid to taller cells that fit the label.

—
className?
string
—
aria-label?
string
—
mode?
"multiple" | "range" | "week" | "single"
—
value?
Date | DateRange | WeekRange | Date[] | null
—
defaultValue?
Date | DateRange | WeekRange | Date[] | null
—
onValueChange?
((date: Date) => void) | ((range: DateRange) => void) | ((week: WeekRange) => void) | ((dates: Date[]) => void)

Called with the picked day's whole row, honouring `weekStartsOn`. Called with the selection sorted by date.

—
minNights?
number

Fewest nights (days between start and end) a finished range may span. While the end is being chosen, days too close are blocked.

—
maxNights?
number

Most nights a finished range may span; farther days are blocked.

—
max?
number

Most days that can be picked; further picks are ignored.

—

Range

calendar.tsx

Two months side by side; pick a start and end day and the band follows the pointer across both until the range closes.

Date Picker Range preview width

API Reference

minDate?
Date

Earliest selectable day (inclusive).

—
maxDate?
Date

Latest selectable day (inclusive).

—
isDateDisabled?
((date: Date) => boolean)

Extra per-day rule, e.g. weekends or booked dates.

—
weekStartsOn?
0 | 1 | 2 | 3 | 4 | 5 | 6

0 = Sunday … 6 = Saturday. Default 0.

—
locale?
string

BCP 47 locale for month, weekday and day labels. Default "en-US" — a fixed default keeps server and client output identical for hydration.

—
month?
Date

Controlled visible month (any day inside it).

—
defaultMonth?
Date

Uncontrolled initial visible month. Default: the selection or today.

—
onMonthChange?
((month: Date) => void)
—
numberOfMonths?
number

Months shown side by side (stacked below `sm`). Default 1. With more than one, days outside each month are left blank so none repeats.

—
showWeekNumber?
boolean

Adds an ISO 8601 week-number column ("Wk") before each row.

—
getDayMeta?
((date: Date) => CalendarDayMeta | null)

Per-day label, tone and blocking, e.g. nightly prices or booked days. Passing it switches the grid to taller cells that fit the label.

—
className?
string
—
aria-label?
string
—
mode?
"multiple" | "range" | "week" | "single"
—
value?
Date | DateRange | WeekRange | Date[] | null
—
defaultValue?
Date | DateRange | WeekRange | Date[] | null
—
onValueChange?
((date: Date) => void) | ((range: DateRange) => void) | ((week: WeekRange) => void) | ((dates: Date[]) => void)

Called with the picked day's whole row, honouring `weekStartsOn`. Called with the selection sorted by date.

—
minNights?
number

Fewest nights (days between start and end) a finished range may span. While the end is being chosen, days too close are blocked.

—
maxNights?
number

Most nights a finished range may span; farther days are blocked.

—
max?
number

Most days that can be picked; further picks are ignored.

—

Date Range Picker

date-range-picker.tsx

Range field whose two-month calendar morphs open beside one-click presets and commits once the end day is picked.

Date Picker Date Range Picker preview width

Install

$ bunx --bun shadcn add @karaui/date-range-picker

API Reference

value?
DateRange | null
—
defaultValue?
DateRange | null
null
onValueChange?
((range: { from: Date; to: Date; }) => void)

Fires once both ends are picked (or a preset is chosen).

—
placeholder?
string
Pick a date range
presets?
DateRangePreset[]

Quick picks listed beside the calendar.

—
numberOfMonths?
number

Months side by side. Default 2 (stacked below `sm`).

2
formatOptions?
DateTimeFormatOptions

Intl options for the trigger label. Default: "Oct 14 – 20, 2026".

{ month: "short", day: "numeric", year: "numeric", }
locale?
string

Default "en-US".

en-US
minDate?
Date
—
maxDate?
Date
—
isDateDisabled?
((date: Date) => boolean)
—
weekStartsOn?
0 | 1 | 2 | 3 | 4 | 5 | 6
—
align?
"end" | "start"
start
disabled?
boolean
—
className?
string
—
aria-label?
string
Choose date range

Multiple Dates

calendar.tsx

Toggle any number of separate days up to a max; picked neighbours in a week merge into one pill.

Date Picker Multiple Dates preview width

API Reference

minDate?
Date

Earliest selectable day (inclusive).

—
maxDate?
Date

Latest selectable day (inclusive).

—
isDateDisabled?
((date: Date) => boolean)

Extra per-day rule, e.g. weekends or booked dates.

—
weekStartsOn?
0 | 1 | 2 | 3 | 4 | 5 | 6

0 = Sunday … 6 = Saturday. Default 0.

—
locale?
string

BCP 47 locale for month, weekday and day labels. Default "en-US" — a fixed default keeps server and client output identical for hydration.

—
month?
Date

Controlled visible month (any day inside it).

—
defaultMonth?
Date

Uncontrolled initial visible month. Default: the selection or today.

—
onMonthChange?
((month: Date) => void)
—
numberOfMonths?
number

Months shown side by side (stacked below `sm`). Default 1. With more than one, days outside each month are left blank so none repeats.

—
showWeekNumber?
boolean

Adds an ISO 8601 week-number column ("Wk") before each row.

—
getDayMeta?
((date: Date) => CalendarDayMeta | null)

Per-day label, tone and blocking, e.g. nightly prices or booked days. Passing it switches the grid to taller cells that fit the label.

—
className?
string
—
aria-label?
string
—
mode?
"multiple" | "range" | "week" | "single"
—
value?
Date | DateRange | WeekRange | Date[] | null
—
defaultValue?
Date | DateRange | WeekRange | Date[] | null
—
onValueChange?
((date: Date) => void) | ((range: DateRange) => void) | ((week: WeekRange) => void) | ((dates: Date[]) => void)

Called with the picked day's whole row, honouring `weekStartsOn`. Called with the selection sorted by date.

—
minNights?
number

Fewest nights (days between start and end) a finished range may span. While the end is being chosen, days too close are blocked.

—
maxNights?
number

Most nights a finished range may span; farther days are blocked.

—
max?
number

Most days that can be picked; further picks are ignored.

—

Week Picker

calendar.tsx

Hovering a day previews its whole week and a click picks it as one pill across the row, with an ISO week-number column; shown as a timesheet week.

Date Picker Week Picker preview width

API Reference

minDate?
Date

Earliest selectable day (inclusive).

—
maxDate?
Date

Latest selectable day (inclusive).

—
isDateDisabled?
((date: Date) => boolean)

Extra per-day rule, e.g. weekends or booked dates.

—
weekStartsOn?
0 | 1 | 2 | 3 | 4 | 5 | 6

0 = Sunday … 6 = Saturday. Default 0.

—
locale?
string

BCP 47 locale for month, weekday and day labels. Default "en-US" — a fixed default keeps server and client output identical for hydration.

—
month?
Date

Controlled visible month (any day inside it).

—
defaultMonth?
Date

Uncontrolled initial visible month. Default: the selection or today.

—
onMonthChange?
((month: Date) => void)
—
numberOfMonths?
number

Months shown side by side (stacked below `sm`). Default 1. With more than one, days outside each month are left blank so none repeats.

—
showWeekNumber?
boolean

Adds an ISO 8601 week-number column ("Wk") before each row.

—
getDayMeta?
((date: Date) => CalendarDayMeta | null)

Per-day label, tone and blocking, e.g. nightly prices or booked days. Passing it switches the grid to taller cells that fit the label.

—
className?
string
—
aria-label?
string
—
mode?
"multiple" | "range" | "week" | "single"
—
value?
Date | DateRange | WeekRange | Date[] | null
—
defaultValue?
Date | DateRange | WeekRange | Date[] | null
—
onValueChange?
((date: Date) => void) | ((range: DateRange) => void) | ((week: WeekRange) => void) | ((dates: Date[]) => void)

Called with the picked day's whole row, honouring `weekStartsOn`. Called with the selection sorted by date.

—
minNights?
number

Fewest nights (days between start and end) a finished range may span. While the end is being chosen, days too close are blocked.

—
maxNights?
number

Most nights a finished range may span; farther days are blocked.

—
max?
number

Most days that can be picked; further picks are ignored.

—

Booking Calendar

booking-calendar.tsx

Two-month stay picker with nightly prices under each day and the cheapest days tinted, booked nights struck through, a minimum stay, and a footer with dates, nights, total and a Reserve button.

Date Picker Booking Calendar preview width

Install

$ bunx --bun shadcn add @karaui/booking-calendar

API Reference

prices
Record<string, number> | ((date: Date) => number | null | undefined)

Nightly price keyed by "YYYY-MM-DD" (the night's check-in date), or a function. Nights without a price can't be booked.

—
booked?
(string | Date)[]

Nights already taken, as dates or "YYYY-MM-DD". They render struck through; the first one after a check-in still works as the check-out.

—
minNights?
number

Fewest nights per stay. Default 1.

1
maxNights?
number

Most nights per stay.

—
currency?
string

ISO 4217 code for prices and the total. Default "USD".

USD
locale?
string

BCP 47 locale. Default "en-US" so server and client output match.

en-US
minDate?
Date

Earliest check-in, typically today (read it after mount).

—
maxDate?
Date
—
value?
DateRange | null
—
defaultValue?
DateRange | null
null
onValueChange?
((range: DateRange | null) => void)
—
defaultMonth?
Date

Uncontrolled first visible month.

—
numberOfMonths?
number

Months side by side. Default 2.

2
weekStartsOn?
0 | 1 | 2 | 3 | 4 | 5 | 6
0
onReserve?
((booking: BookingSummary) => void)

Called by the Reserve button with the finished stay.

—
reserveLabel?
string

Reserve button text. Default "Reserve".

Reserve
className?
string
—

Time Picker

time-picker.tsx

iOS-style hour, minute and AM/PM drums composed from WheelPicker, inline or as a time field whose wheels morph open and commit on Done.

Date Picker Time Picker preview width

Install

$ bunx --bun shadcn add @karaui/time-picker

API Reference

toTimeString

hours
number
—
minutes
number
—

TimePicker

value?
TimeValue

Controlled time (24-hour).

—
defaultValue?
TimeValue

Uncontrolled initial time. Default 09:00.

{ hours: 9, minutes: 0 }
onValueChange?
((time: TimeValue) => void)

Fires as each wheel settles on a row. Always 24-hour.

—
hourCycle?
12 | 24

12 shows hour 12–11 plus an AM/PM wheel; 24 shows 00–23. Default 12.

12
minuteStep?
number

Minute wheel granularity. A value off the grid displays snapped to the nearest step and the first wheel turn commits the snapped minute. Default 5.

5
visibleCount?
number

Rows visible per wheel, odd. Default 5.

5
itemHeight?
number

Row height in px. Default 36.

36
sound?
boolean

Tick sound per row crossed (WheelPicker's `sound`). Default false.

false
disabled?
boolean
false
className?
string
—
aria-label?
string

Prefix for each wheel's accessible name. Default "Time".

Time

TimeField

value?
TimeValue | null

Controlled committed time; null shows the placeholder.

—
defaultValue?
TimeValue | null
null
onValueChange?
((time: TimeValue) => void)

Fires once, when Done is pressed. Always 24-hour.

—
initialTime?
TimeValue

Where the wheels start while the field is empty. Default 09:00.

{ hours: 9, minutes: 0 }
placeholder?
string
Pick a time
locale?
string

Default "en-US".

en-US
align?
"end" | "start"
start
className?
string
—
disabled?
boolean
—
aria-label?
string

Prefix for each wheel's accessible name. Default "Time".

Choose time
hourCycle?
12 | 24

12 shows hour 12–11 plus an AM/PM wheel; 24 shows 00–23. Default 12.

12
minuteStep?
number

Minute wheel granularity. A value off the grid displays snapped to the nearest step and the first wheel turn commits the snapped minute. Default 5.

—
visibleCount?
number

Rows visible per wheel, odd. Default 5.

—
itemHeight?
number

Row height in px. Default 36.

—
sound?
boolean

Tick sound per row crossed (WheelPicker's `sound`). Default false.

—

Date & Time Picker

date-time-picker.tsx

One field whose panel morphs open with the calendar beside time wheels; edits a draft and commits on Done, labelled like "Oct 14, 2026, 9:30 AM".

Date Picker Date & Time Picker preview width

Install

$ bunx --bun shadcn add @karaui/date-time-picker

API Reference

value?
Date | null

Controlled committed date and time; null shows the placeholder.

—
defaultValue?
Date | null
null
onValueChange?
((date: Date) => void)

Fires once, when Done is pressed.

—
placeholder?
string
Pick a date and time
formatOptions?
DateTimeFormatOptions

Intl options for the trigger label. Default `{ dateStyle: "medium", timeStyle: "short" }` → "Oct 14, 2026, 9:30 AM" in en-US.

{ dateStyle: "medium", timeStyle: "short", }
locale?
string

Default "en-US".

en-US
hourCycle?
12 | 24

12 adds an AM/PM wheel; 24 shows 00–23. Also sets the label's clock. Default 12.

12
minuteStep?
number

Minute wheel granularity. Default 5.

5
initialTime?
TimeValue

Where the wheels start while the field is empty. Default 09:00.

{ hours: 9, minutes: 0 }
minDate?
Date

Earliest moment. Days before it are disabled, and a committed value earlier on that same day is clamped up to it.

—
maxDate?
Date

Latest moment, clamped the same way.

—
isDateDisabled?
((date: Date) => boolean)
—
weekStartsOn?
0 | 1 | 2 | 3 | 4 | 5 | 6
—
align?
"end" | "start"
start
disabled?
boolean
—
className?
string
—
aria-label?
string
Choose date and time

Month Picker

month-picker.tsx

Twelve-month grid with a gliding selection pill, year slides and a zoom-out year grid, single or range mode, min/max and full keyboard navigation, plus a popover month field.

Date Picker Month Picker preview width

Install

$ bunx --bun shadcn add @karaui/month-picker

API Reference

MonthPicker

minDate?
Date

Earliest selectable month (any day inside it).

—
maxDate?
Date

Latest selectable month (any day inside it).

—
isMonthDisabled?
((month: Date) => boolean)

Extra per-month rule; receives the first of the month.

—
defaultYear?
number

Year shown first when nothing is selected. Pass it explicitly for SSR — without it the current year is read after mount.

—
locale?
string

BCP 47 locale for month names. Default "en-US".

—
className?
string
—
aria-label?
string
—
mode?
"range" | "single"
—
value?
Date | MonthRange | null

First of the selected month.

—
defaultValue?
Date | MonthRange | null
—
onValueChange?
((month: Date) => void) | ((range: MonthRange) => void)

Called with the first of the picked month.

—

MonthField

value?
Date | null
—
defaultValue?
Date | null
null
onValueChange?
((month: Date) => void)
—
placeholder?
string
Pick a month
formatOptions?
DateTimeFormatOptions

Intl options for the trigger label. Default "October 2026".

{ month: "long", year: "numeric", }
align?
"end" | "start"
start
disabled?
boolean
—
className?
string
—
aria-label?
string
Choose month
minDate?
Date

Earliest selectable month (any day inside it).

—
maxDate?
Date

Latest selectable month (any day inside it).

—
isMonthDisabled?
((month: Date) => boolean)

Extra per-month rule; receives the first of the month.

—
defaultYear?
number

Year shown first when nothing is selected. Pass it explicitly for SSR — without it the current year is read after mount.

—
locale?
string

BCP 47 locale for month names. Default "en-US".

en-US

Updated