useStandaloneTimePicker

Manages time state with open/close and click-outside behavior.

Import

import { useStandaloneTimePicker } from "react-date-range-picker-headless";

Usage

import { useState } from "react";
import { useStandaloneTimePicker } from "react-date-range-picker-headless";
function MyTimePicker() {
const [time, setTime] = useState<Date | null>(null);
const picker = useStandaloneTimePicker({
value: time,
onChange: setTime,
time: { precision: "minute", hourFormat: "24", minuteStep: 5 },
placeholder: "Select time",
});
return (
<div ref={picker.containerRef}>
<button onClick={picker.handleToggle}>
{picker.hasValue ? picker.displayValue : "Select time"}
</button>
{picker.isOpen && (
<div ref={picker.popupRef} onKeyDown={picker.handleKeyDown}>
<div>
<span>{String(picker.tempHour).padStart(2, "0")}</span>
<span>:</span>
<span>{String(picker.tempMinute).padStart(2, "0")}</span>
</div>
{/* Hook up hour/minute controls */}
<input
type="range"
min={0}
max={23}
value={picker.tempHour}
onChange={(e) => picker.handleHourChange(Number(e.target.value))}
/>
<input
type="range"
min={0}
max={55}
step={5}
value={picker.tempMinute}
onChange={(e) => picker.handleMinuteChange(Number(e.target.value))}
/>
<div>
<button onClick={picker.handleClear}>Clear</button>
<button onClick={picker.handleCancel}>Cancel</button>
<button onClick={picker.handleConfirm}>Confirm</button>
</div>
</div>
)}
</div>
);
}

Options

OptionTypeDefaultDescription
valueDate | nullRequired. Current time as a Date object (only the time portion is used).
onChange(date: Date | null) => voidRequired. Called when the time is confirmed.
timeTimeConfig{ precision: "minute", hourFormat: "24", minuteStep: 5, secondStep: 1 }Time picker configuration.
localePartial<Locale>DEFAULT_LOCALEOverride locale strings.
displayFormatstringCustom format string for the trigger display.
placeholderstringPlaceholder text when no value is selected.
openbooleanControlled open state.
initialOpenbooleanfalseInitial open state (uncontrolled).
onOpenChange(open: boolean) => voidCallback when open state changes.
requiredbooleanfalseWhen true, handleClear is a no-op.
inlinebooleanfalseAlways show the panel without a trigger/popup.
namestringHidden input name for form submission.

Return Values

NameTypeDescription
isOpenbooleanWhether the popup is currently open.
handleOpen() => voidOpen the popup.
handleClose() => voidClose the popup.
handleToggle() => voidToggle the popup.
tempHournumberCurrent temporary hour value.
tempMinutenumberCurrent temporary minute value.
tempSecondnumberCurrent temporary second value.
tempPeriodTimePeriodCurrent AM/PM period.
handleHourChange(hour: number) => voidUpdate the temporary hour.
handleMinuteChange(minute: number) => voidUpdate the temporary minute.
handleSecondChange(second: number) => voidUpdate the temporary second.
handlePeriodChange(period: TimePeriod) => voidUpdate AM/PM period.
handleConfirm() => voidConfirm the temporary time, call onChange, and close the popup.
handleCancel() => voidRevert to the original value and close the popup.
handleClear() => voidClear the value and close. No-op if required.
displayValuestringFormatted time string for the trigger (committed value).
timeDisplayValuestringFormatted time string for the panel (temporary value).
hasValuebooleanWhether a time value is currently set.
canConfirmbooleanWhether the confirm button should be enabled.
localeLocaleResolved locale object.
resolvedTimeConfigRequired<TimeConfig>Fully resolved time configuration.
containerRefRefObject<HTMLDivElement | null>Ref for the outer container (used for click-outside detection).
popupRefRefObject<HTMLDivElement | null>Ref for the popup element (used for click-outside detection).
handleKeyDown(e: KeyboardEvent) => voidKeyboard handler (Escape to cancel).

Key Behaviors

Open/Close

The popup can be controlled or uncontrolled. When open is provided, the hook uses it as the source of truth. Otherwise, internal state is used with initialOpen as the starting value.

Click Outside

Clicking outside both containerRef and popupRef triggers handleCancel, reverting to the original value and closing the popup.

Keyboard

Pressing Escape while the popup is open triggers handleCancel.

Inline Mode

When inline is true, the panel is always visible and changes are applied immediately (auto-sync). The open/close logic is bypassed.

Temporary State Pattern

This hook maintains temporary state that only commits when handleConfirm is called:

  • handleConfirm — writes temporary state to onChange and closes the popup
  • handleCancel — reverts temporary state to the current value and closes
  • handleClear — calls onChange(null) and closes

Display Values

  • displayValue — formatted string of the committed value (for the trigger)
  • timeDisplayValue — formatted string of the temporary values (for the panel)