TimePicker
time-pickerSelects a time from hour and minute option controls.
Usage
Basic usage
Point trigger pops up hour/minute columns, the value is fixed-width 24-hour text HH:mm.
<TimePicker defaultValue="09:30" />With seconds
withSeconds Add the seconds column, and the value shape becomes HH:mm:ss.
<TimePicker withSeconds defaultValue="09:30:15" />Stepper
minuteStep only lists the minutes of the entire step, so users do not need to choose from 60 in scenarios such as shift scheduling/appointment.
<TimePicker minuteStep={15} defaultValue="09:30" />Limited range
minTime / maxTime Gray out unreachable values column by column. The criterion is "whether the entire segment intersects with the range" - when min=09:30, 9 o'clock is still available, but the minutes before 30 minutes within 9 o'clock are prohibited.
<TimePicker minTime="09:30" maxTime="18:00" defaultValue="10:00" />Size
size uses the same scale as Input and Select (sm 32px / md 40px / lg 48px), so controls sitting on one form row line up.
<TimePicker size="sm" defaultValue="09:30" />
<TimePicker size="md" defaultValue="09:30" />
<TimePicker size="lg" defaultValue="09:30" />Disabled / Read Only
disabled is grayed out and cannot be opened; readOnly panel can be viewed but cannot be selected.
<TimePicker defaultValue="09:30" disabled />
<TimePicker defaultValue="09:30" readOnly />When to use
Use TimePicker for popup-based time selection in schedules, reservations, or business hours. Step sizes and the Now shortcut work well when choices should align to whole or half hours.
Use TimeField for keyboard-first segmented input, DateTimePicker for a combined date and time, or DatePicker for a date only.
Import
import { TimePicker } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| value | string | null | - | Controlled value in zero-padded 24-hour "HH:mm" or "HH:mm:ss" format, depending on withSeconds. |
| defaultValue | string | null | - | Initial value in uncontrolled mode, with the same shape as value. |
| withSeconds | boolean | false | Whether to show the seconds column and include seconds in the value. |
| size | "sm" | "md" | "lg" | "md" | Trigger size, on the same scale as Input (32 / 40 / 48px), so controls on one form row line up. |
| minuteStep | number | 1 | Increment between minute options; 5, 15, and 30 are common choices. |
| secondStep | number | 1 | Increment between second options. |
| minTime | string | - | Earliest selectable time, inclusive, with the same shape as value. |
| maxTime | string | - | Latest selectable time, inclusive. |
| placeholder | string | "\u9009\u62e9\u65f6\u95f4" | Trigger placeholder; the built-in Chinese copy means “Select time.” |
| clearable | boolean | true | Whether to show a clear button when the picker has a value and is neither disabled nor read-only. |
| showNow | boolean | true | Shows a shortcut with built-in Chinese copy "\u6b64\u523b" (Now), rounded down to the configured step. |
| disabled | boolean | false | Disables the trigger and prevents the panel from opening. |
| readOnly | boolean | false | Allows the panel to open but prevents selection. |
| aria-label | string | - | Accessible name for an unlabeled trigger. |
| className | string | - | Additional class name for the outer trigger container. |
Events
| Event | Type | Description |
|---|---|---|
| onValueChange | (value: string | null) => void | Called with the selected value, or null when cleared. |
Example
<TimePicker defaultValue="09:30" />
// With seconds
<TimePicker withSeconds defaultValue="09:30:15" />
// 15-minute increments
<TimePicker minuteStep={15} defaultValue="09:30" />
// Business hours window
<TimePicker minTime="09:30" maxTime="18:00" defaultValue="10:00" />The package also exports pure functions for form validation, so consumers do not need to parse the time string again:
import { parseTime, formatTimeParts, clampTime, snapToStep } from "@hulianui/ui"
parseTime("9:5") // { h: 9, m: 5, s: 0 }; invalid/out-of-range input returns null
formatTimeParts({h:9,m:5,s:0}, false) // "09:05"
clampTime({h:8,m:0,s:0}, false, "09:30") // { h: 9, m: 30, s: 0 }
snapToStep({h:9,m:37,s:0}, 15) // { h: 9, m: 30, s: 0 }ThePartssuffix avoids a collision with Video's existingformatTime, which converts seconds tomm:ss.
Usage guidelines
- Values are fixed-width strings, not `Date` objects. Lexical order of
"HH:mm[:ss]"matches time order, so bounds compare directly without timezone effects. Add a date explicitly if the application needs aDate. - A column option is disabled only when its entire interval falls outside the range. With
minTime="09:30", hour 09 remains available because 09:30-09:59 is valid, while minute values before 30 are disabled when hour 09 is active. - An empty picker uses `clamp(00:00:00, [min,max])` as its working base. With
minTime="09:30", this keeps the minute column usable even before the user selects an hour. minuteStepchanges only the candidate list; it does not validate external values. WithminuteStep={15},value="09:37"has no matching minute item and is not highlighted. CallsnapToStepfirst when alignment is required.- Switching
withSecondschanges the external value shape ("09:30"↔"09:30:15"). Normalize stored values when switching modes. - TimePicker and TimeField share the same fixed-width
"HH:mm[:ss]"format, so applications can switch between popup and keyboard interactions without converting values. - The trigger is a
role="combobox"button, and native attributes that are not listed in Props (aria-*,data-*,id,title,onBlur, ...) land on it rather than on the outer container, which is the element that takes focus and that screen readers announce (#315). - Inside Field the label's
htmlFor,aria-describedby,invalid, anddisabledare wired to the trigger automatically, and so is thearia-requiredinjected by<Field required>. That chain was broken until #315 (the label pointed at an id that did not exist, so screen readers never announced the field name); upgrading needs no call-site change. - Query the trigger by role with
getByRole("combobox")in tests, not"button"anymore.comboboxis not a name-from-content role, so the accessible name comes fromaria-labelor theFieldlabel rather than from the time text shown on the trigger.
Related
TimeField · DatePicker · DateTimePicker · DateRangePicker · Calendar · Scheduler
Playground
<TimePicker
value={time}
onValueChange={setTime}
/>