DatePicker

A trigger button that opens a calendar popup for selecting a single date, with full keyboard navigation, min/max bounds, and no external date library.

Installation

npx dafink-ui add date-picker

Demo

Arrow keys navigate the calendar grid.

Type digits or use arrow keys on the time segments.

Reminder time
12
00
00
AM

Time-only picker, no calendar grid.

Props

NameTypeDefaultDescription
valueDate | nullundefinedThe currently selected date (controlled).
onChange(date: Date) => voidundefinedCalled when the user selects a day.
placeholderstring'Pick a date'Text shown when no date is selected.
granularity'date' | 'time' | 'datetime''date'Controls whether the popup shows a calendar grid, a time-entry row, or both.
minDateundefinedEarliest selectable date.
maxDateundefinedLatest selectable date.
disabledbooleanfalseDisables the trigger.
labelstringundefinedVisible label above the trigger.
hintstringundefinedHelper text below the trigger.
errorstringundefinedError message; applies error border styling.
panelSide'top' | 'bottom''bottom'Which side of the trigger the calendar panel opens on. Use 'top' when the trigger sits near the bottom of its container.
classNamestring''Additional classes on the root wrapper.

Accessibility

DatePicker's popup is a non-modal dialog (role="dialog", no aria-modal): focus moves into the calendar grid (or straight to the Hours segment for a time-only picker) on open, but is never trapped — Tab either redirects focus (into the time row, for a date-and-time picker) or closes the popup and moves on natively, the same as Escape. The calendar grid uses roving tabindex: exactly one day button is a tab stop at a time, and arrow keys move that roving focus across month boundaries automatically. Time segments (Hours/Minutes/Seconds/AM-PM) deliberately break from roving tabindex — each is its own independent tab stop (role="spinbutton") and Arrow Up/Down change its value immediately rather than just moving focus, matching how a native time input behaves.

KeyFunction
arrow leftMoves the focused day back one day, crossing into the previous month if needed.
arrow rightMoves the focused day forward one day, crossing into the next month if needed.
arrow upMoves the focused day back one week.
arrow downMoves the focused day forward one week.
homeJumps to the current week's Sunday.
endJumps to the current week's Saturday.
page upNavigates to the previous month.
page downNavigates to the next month.
enterSelects the focused day; closes the popup for a date-only picker, or advances to the time row for a date-and-time picker.
escapeCloses whatever popup is open (calendar, time row, or time wheel) and returns focus to the button that opened it.
tabCloses the popup natively when there is no time row after the grid, or moves focus onward into the time segments for a date-and-time picker.