A time of day for meetings, shifts, pickups and opening hours. Segmented input where each part is a spinbutton (type digits, ↑ ↓, ← →), an optional slot list every N minutes, and a start–end range with duration. The value is always "HH:mm" 24h; the display follows the locale (2:30 PM / 14:30).
Type digits or use ↑ ↓.
value: 14:30
Installation
The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";
Usage
import { Field, TimePicker } from "@vamos-ui/react";
<Field label="Meeting starts">
<TimePicker value={time} onValueChange={setTime} slots step={30} />
</Field>Each segment is role="spinbutton" with aria-valuenow / min / max / valuetext inside a role="group" labelled by the Field. Digits type ahead and auto-advance; Backspace clears a segment, then moves back; : or . jumps to the next segment; A / P set the period.
The input group is always dir="ltr" so times read the same in right-to-left pages.
Examples
Slot list
slots opens a listbox every step minutes between min and max; disabledTimes greys out a lunch break.
Store open 09:00–18:00, every 30 minutes.
12-hour and 24-hour
Segment order, separator and AM/PM labels come from Intl. Both fields share one "HH:mm" value.
Press A or P to switch.
Same value, 24-hour display.
Shift start and end
TimeRangePicker shows the duration and flags an end before the start, unless overnight is set (then +1 day).
Front desk, Monday to Friday.
Ends the next morning.
Seconds, sizes & states
seconds adds a segment; disabled, read-only, out of range (aria-invalid) and sizes.
Opening hours are 10:00–22:00.
API
TimeInput / TimePicker
| Prop | Type | Default |
|---|---|---|
value / defaultValue"HH:mm" ("HH:mm:ss" with seconds), 24h. | string | null | — |
onValueChangeA complete time, or null when emptied or left incomplete. | (value: string | null) => void | — |
hourCycleDisplay only. Default from the locale (en-US 12, tr 24). | 12 | 24 | — |
stepMinutes per ↑ / ↓ on the minute segment and between slots. | number | 1 (TimeInput) · 15 (TimePicker) |
secondsAdds a seconds segment. | boolean | false |
min / maxAllowed range (HH:mm). Outside it the group is aria-invalid. | string | — |
disabledTimesTimes that are not allowed (also disabled in the slot list). | (time: string) => boolean | — |
slotsTimePicker only: slot list popover. | boolean | false |
slotRangeTimePicker only: first / last slot. Default min / max or the whole day. | { start: string; end: string } | — |
nameHidden input submitting HH:mm. | string | — |
size / variantBox look (controlVariants). | "sm" | "md" | "lg" / "default" | "ghost" | "md" / "default" |
invalid / disabled / readOnly / requiredAlso read from Field. | boolean | — |
icon / trailingLeading icon (null hides the clock) and end content. | ReactNode | — |
labelstimePicker namespace: hour, minute, second, dayPeriod, showTimes, durations. | Partial<TimePickerLabels> | — |
TimeRangePicker
| Prop | Type | Default |
|---|---|---|
value / defaultValueTwo HH:mm values. | { start: string | null; end: string | null } | — |
onValueChangeAny change of either end. | (value: TimeRange) => void | — |
overnightAn earlier end means the next day (night shift). | boolean | false |
showDurationDuration hint, announced politely. | boolean | true |
nameStart / nameEndHidden inputs. | string | — |