Skip to main content

useDatePicker

The hook behind <DatePicker>. Use it when you need a fully custom UI that the compound components can't express.

import { useDatePicker } from '@kalyx/react';

Signature

function useDatePicker(options?: UseDatePickerOptions): UseDatePickerReturn;

Options

FieldTypeDefaultDescription
valueISODateString | nullControlled value.
defaultValueISODateStringUncontrolled initial value.
onChange(value: ISODateString | null) => voidChange callback.
disabledDisabledRule[][]Disable rules.
weekStartsOn0 | 10Week start.
adapterDateAdapterDateFnsAdapterCustom adapter.
displayTimezonestringIANA zone. When set, selectDate stores civil-midnight-in-tz and today/selected highlighting uses civil-day comparison. See Timezone.

Return

FieldTypeDescription
valueISODateString | nullCurrent value.
isOpenbooleanPopover state.
open() => voidOpen the popover.
close() => voidClose the popover.
toggle() => voidToggle the popover.
selectDate(iso: ISODateString | null) => voidSet value programmatically.
viewMonthISODateStringFirst-day-of-visible-month.
setViewMonth(iso: ISODateString) => voidJump to a month.
calendarCalendarGrid6×7 grid of CalendarDays.
focusedDateISODateStringCurrently keyboard-focused day.
setFocusedDate(iso: ISODateString) => voidMove focus.
previousMonth() => voidShorthand for setViewMonth(prev).
nextMonth() => voidShorthand for setViewMonth(next).
pickerIdstringStable useId-based ID for ARIA wiring.
adapterDateAdapterThe resolved adapter.

CalendarDay

type CalendarDay = {
isoString: ISODateString;
dayNumber: number; // 1–31
isCurrentMonth: boolean;
isToday: boolean;
isSelected: boolean;
isDisabled: boolean;
isFocused: boolean;
isRangeStart: boolean; // always false for useDatePicker
isRangeEnd: boolean; // always false for useDatePicker
isInRange: boolean; // always false for useDatePicker
};

Example — custom grid

import { useDatePicker } from '@kalyx/react';

export function MiniCalendar() {
const {
value,
calendar,
viewMonth,
previousMonth,
nextMonth,
selectDate,
} = useDatePicker({
defaultValue: new Date().toISOString(),
onChange: (v) => console.log(v),
});

return (
<div>
<header>
<button onClick={previousMonth} aria-label="Previous"></button>
<span>{viewMonth.slice(0, 7)}</span>
<button onClick={nextMonth} aria-label="Next"></button>
</header>
<div className="grid grid-cols-7">
{calendar.flat().map((day) => (
<button
key={day.isoString}
aria-selected={day.isSelected}
disabled={day.isDisabled}
onClick={() => selectDate(day.isoString)}
className={[
day.isCurrentMonth ? '' : 'opacity-40',
day.isToday ? 'ring-1 ring-indigo-500' : '',
day.isSelected ? 'bg-indigo-600 text-white' : '',
].join(' ')}>
{day.dayNumber}
</button>
))}
</div>
</div>
);
}

When to use the hook vs components

NeedUse
Standard calendar, some styling<DatePicker.Calendar classNames={…}>
Standard calendar, custom DOM slots<DatePicker> + custom classNames
Non-grid layout (week view, agenda, inline list)useDatePicker
Embedded in a design-system primitiveuseDatePicker wrapped in your component