Date Picker

Pro

A calendar surface plus two ready pickers, single date and range, over Radix Popover with native Date math and no date dependency. Selection is a solid ink fill; the in-range days take a soft grey.

Installation#

# One-time setup (tokens + lib helpers)npx koalaui-cli@latest init# Activate your Pro license (once per machine)npx koalaui-cli@latest login <key># Add this component (its dependencies come along)npx koalaui-cli@latest add date-picker

Usage#

This example is part of Koala UI Pro

The preview is yours to explore. Its code comes with a Pro license, paid once and used in every project.

Have a license? Unlock it here

Calendar#

The Calendar is the standalone grid the pickers wrap. Use it directly when you need an always-open calendar. The caption cycles day → month → year views; arrow keys move the focused day, PageUp/PageDown move a month, Home/End jump to the week edges.

October 2026

Range selection#

Set mode="range" to select a { from, to } span. The first click sets the start, the second closes the range; hovering previews the span. Show multiple months with numberOfMonths.

October 2026, November 2026
October 2026
November 2026

Presets#

Pass presets to render a quick-pick rail. Use presets (boolean) for the built-in set, or pass your own array. The single-date set ships getDatePresets(); the range set ships getDateRangePresets() with eleven common spans (Today, Last 7 days, This month, Last year, …).

Range with presets#

The combination most analytics surfaces want: a two-month range picker with the full preset rail.

Sizes#

Constraints#

Bound the range with min / max, or disable arbitrary days with isDateDisabled. Disabled days are inert and struck through.

Density#

Like the rest of Koala, the calendar honors density: compact (the default, or whatever the nearest DensityProvider sets) keeps 32px cells and a 32px trigger for dense application UI; comfortable opens them to 36px.

Inside a Field#

Drop a picker inside a Field and it auto-wires the label, hint, id, and error/disabled state, with no manual props.

Your subscription begins on this date.

API reference#

Calendar

The standalone month grid the pickers wrap, a <div> with a roving-tabindex role="grid". Takes className on its root, merged last, as every export here does.

PropTypeDefaultDescription
mode"single" | "range""single"Pick one Date, or a DateRange of { from, to }.
selectedDate | DateRange-Controlled selection: a Date in single mode, a DateRange in range mode.
defaultSelectedDate | DateRange-Initial selection when uncontrolled.
onSelect(value: Date | DateRange | undefined) => void-Called with the new selection; a range is { from } until its second click.
monthDate-Controlled displayed month.
defaultMonthDate-Initial month when uncontrolled; otherwise the selection's month, or today's.
onMonthChange(month: Date) => void-Called when the displayed month changes.
minDate-Earliest selectable day, inclusive.
maxDate-Latest selectable day, inclusive.
isDateDisabled(date: Date) => boolean-Disable arbitrary days, such as weekends. Disabled days are inert and struck through.
weekStartsOn0 | 1 | 2 | 3 | 4 | 5 | 61First column of the week, 0 for Sunday; Monday by default.
localestring-BCP-47 locale for month and weekday labels. Defaults to the visitor's; server and hydrating renders use en-US, then the visitor's takes over.
numberOfMonthsnumber1Month grids shown side by side. The caption switches to month and year views only with one.
density"comfortable" | "compact""compact"Cell size: 36 or 32px. Falls back to the nearest DensityProvider.
Data attributeDescription
data-selectedOn a day button: the selected day or a range endpoint. On a month or year cell: the displayed one.
data-todayOn today's day button; set after hydration, never on the server.
data-outsideOn a day from the neighbouring month.
data-disabledOn a day outside min/max or matched by isDateDisabled.
data-currentOn the month or year cell that holds today.

DatePicker

A trigger that opens a Calendar in a Radix Popover, for one date; it closes on pick. Reads Field context for its id, description, disabled and error state.

PropTypeDefaultDescription
valueDate-Controlled date.
defaultValueDate-Initial date when uncontrolled.
onChange(date: Date | undefined) => void-Called on pick, preset or clear.
placeholderstring"Pick a date"Trigger label while no date is set.
size"sm" | "md" | "lg""sm"Trigger height: 32, 36 or 40px. Unset, it follows density (sm compact, md comfortable), or the size a Form imposes.
blockbooleanfalseStretch the trigger to its container's width.
clearablebooleanfalseShow a clear button in the trigger once a value is set.
presetsboolean | DatePreset[]-A quick-pick rail: true for the built-in set, or your own { label, value } items.
format(date: Date) => string-Format each date in the trigger label. Defaults to the locale's medium date.
minDate-Earliest selectable day, inclusive.
maxDate-Latest selectable day, inclusive.
isDateDisabled(date: Date) => boolean-Disable arbitrary days, such as weekends. Disabled days are inert and struck through.
weekStartsOn0 | 1 | 2 | 3 | 4 | 5 | 61First column of the week, 0 for Sunday; Monday by default.
localestring-BCP-47 locale for month and weekday labels. Defaults to the visitor's; server and hydrating renders use en-US, then the visitor's takes over.
numberOfMonthsnumber1Month grids shown side by side.
density"comfortable" | "compact""compact"Calendar cell size (36 or 32px) and the trigger's default size. Falls back to the nearest DensityProvider.
align"start" | "center" | "end""start"Popover alignment against the trigger; it opens 8px below.
disabledboolean-Disable the trigger. Inside a Field, read from the field.
hasErrorboolean-Mark the trigger invalid (aria-invalid, destructive border). Inside a Field, read from the field.
idstring-The trigger's id. Inside a Field, read from the field so its label points here.
triggerClassNamestring-Extra classes for the trigger; className lands on the trigger too.
Data attributeDescription
data-stateOn the trigger: "open" or "closed".
data-placeholderOn the trigger while no value is set.
data-activeOn the preset that matches the current value.
CSS variableDescription
--surfaceRead by the trigger as its fill (falls back to --background); the popover sets it to var(--popover).

DateRangePicker

The same picker for a DateRange; it closes once both ends are set or a preset is chosen. Reads Field context like DatePicker.

PropTypeDefaultDescription
valueDateRange-Controlled range, { from, to }.
defaultValueDateRange-Initial range when uncontrolled.
onChange(range: DateRange | undefined) => void-Called on each click, preset or clear.
placeholderstring"Pick a date range"Trigger label while no start is set.
size"sm" | "md" | "lg""sm"Trigger height: 32, 36 or 40px. Unset, it follows density (sm compact, md comfortable), or the size a Form imposes.
blockbooleanfalseStretch the trigger to its container's width.
clearablebooleanfalseShow a clear button in the trigger once a value is set.
presetsboolean | DateRangePreset[]-A quick-pick rail: true for the built-in set, or your own { label, value } items.
format(date: Date) => string-Format each date in the trigger label. Defaults to the locale's medium date.
minDate-Earliest selectable day, inclusive.
maxDate-Latest selectable day, inclusive.
isDateDisabled(date: Date) => boolean-Disable arbitrary days, such as weekends. Disabled days are inert and struck through.
weekStartsOn0 | 1 | 2 | 3 | 4 | 5 | 61First column of the week, 0 for Sunday; Monday by default.
localestring-BCP-47 locale for month and weekday labels. Defaults to the visitor's; server and hydrating renders use en-US, then the visitor's takes over.
numberOfMonthsnumber2Month grids shown side by side.
density"comfortable" | "compact""compact"Calendar cell size (36 or 32px) and the trigger's default size. Falls back to the nearest DensityProvider.
align"start" | "center" | "end""start"Popover alignment against the trigger; it opens 8px below.
disabledboolean-Disable the trigger. Inside a Field, read from the field.
hasErrorboolean-Mark the trigger invalid (aria-invalid, destructive border). Inside a Field, read from the field.
idstring-The trigger's id. Inside a Field, read from the field so its label points here.
triggerClassNamestring-Extra classes for the trigger; className lands on the trigger too.
Data attributeDescription
data-stateOn the trigger: "open" or "closed".
data-placeholderOn the trigger while no value is set.
data-activeOn the preset that matches the current value.
CSS variableDescription
--surfaceRead by the trigger as its fill (falls back to --background); the popover sets it to var(--popover).

getDatePresets

Returns the built-in single-date set: Today, Yesterday, Tomorrow, In a week, In two weeks, In a month.

PropTypeDefaultDescription
nowDatenew Date()The day the presets are relative to.

getDateRangePresets

Returns the built-in eleven ranges, from Today and Last 7 days to This month and Last year.

PropTypeDefaultDescription
nowDatenew Date()The day the presets are relative to.
weekStartsOn0 | 1 | 2 | 3 | 4 | 5 | 61Where This week and Last week begin.

FAQ#

Use Calendar when you need an always-open grid inline on the page, such as a booking surface or a sidebar. DatePicker and DateRangePicker wrap that same Calendar in a Radix Popover with a trigger, so prefer them whenever the calendar should open from a field-like button.