Time Field
Accessible, unstyled segmented time input with 12/24-hour clocks and hour/minute/second granularity.
| Package | @vizejs/ui/time-field |
| Maturity | stable |
| Own the source | vize lib pull time-field |
| Requires | controllable-state, date-field, id, locale |
| Aliases | time input, segmented time, clock input, hh:mm |
| Covers | WAI-ARIA spinbutton, React Aria TimeField, Reka UI TimeField, HTML input type=time |
Usage
import { TimeField } from "@vizejs/ui/time-field";
Or copy the source into your project with vize lib pull time-field (see Source Distribution).
API
TimeField
Source: src/families/date-time/time-field/time-field.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
id |
string | null | undefined |
undefined |
Consumer-owned group id; nullish values use a deterministic fallback. |
name |
string | undefined |
undefined |
Hidden input name that submits HH:MM or HH:MM:SS with forms. |
modelValue |
PlainTime | null | undefined |
undefined |
Controlled time; undefined selects uncontrolled mode and null clears. |
defaultValue |
PlainTime | null | undefined |
null |
Initial uncontrolled time and native form-reset target. |
min |
PlainTime | null | undefined |
undefined |
Earliest valid time; earlier values mark the field invalid. |
max |
PlainTime | null | undefined |
undefined |
Latest valid time; later values mark the field invalid. |
hourCycle |
HourCycle | undefined |
undefined |
12 shows 1–12 plus an AM/PM segment, 24 shows 0–23; defaults to the locale clock. |
granularity |
TimeGranularity | undefined |
"minute" |
Smallest edited unit; second adds a seconds segment. |
placeholderValue |
PlainTime | null | undefined |
{ hour: 0, minute: 0, second: 0 } |
Time whose segments seed arrow-key stepping from empty. |
locale |
string | undefined |
undefined |
BCP 47 locale deciding segment order, clock, and labels; defaults to the nearest LocaleProvider. |
dir |
"ltr" | "rtl" | undefined |
undefined |
Text direction for arrow-key segment movement; defaults to the nearest LocaleProvider. |
disabled |
boolean | undefined |
false |
Remove every segment from focus and editing. |
readOnly |
boolean | undefined |
false |
Keep segments focusable while blocking edits. |
required |
boolean | undefined |
false |
Require a complete value; participates in native form validation. |
invalidMessage |
string | undefined |
"Invalid value" |
Custom validity message reported while the value is out of range or unavailable. |
placeholders |
FieldSegmentPlaceholders | undefined |
{ hour: "––", minute: "––", second: "––", dayPeriod: "––" } |
Placeholder text for empty segments. |
emptyText |
string | undefined |
"Empty" |
Text announced for empty segments. |
ariaLabel |
string | undefined |
undefined |
Accessible name for the segment group. |
ariaLabelledby |
string | undefined |
undefined |
Ids that label the segment group. |
ariaDescribedby |
string | undefined |
undefined |
Ids that describe the group and every segment. |
ariaErrormessage |
string | undefined |
undefined |
Id of the validation message used while invalid. |
ariaInvalid |
boolean | undefined |
false |
Force the invalid state in addition to built-in min/max validation. |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue |
[value: PlainTime | null] |
Fired when segments request a new controlled time or null while incomplete. |
change |
[value: PlainTime | null, previous: PlainTime | null, nativeEvent: Event | null] |
Fired after a distinct committed time with the previous time and triggering event. |
Slots
| Slot | Slot props | Description |
|---|---|---|
default |
TimeFieldSlotState |
Extra content after the segments, such as a picker trigger. Receives field state. |
segment |
FieldSegmentState |
Segment content. Receives the segment state; defaults to its text. |
Behavior
Normative state x input -> outcome table for time-field.vue
(@vizejs/ui/time-field). TimeField shares the DateField segment engine, so
DateField rows F2–F8, F10–F12, and F15 (native required validation) apply to hour, minute, second, and day-period
segments. Every row below is proven by the named test.
| # | State | Input | Outcome | Proven by |
|---|---|---|---|---|
| T1 | locale clock | render | segment order, hour padding, and day-period labels follow Intl; hourCycle forces 12 or 24; granularity adds or removes minute/second segments |
renders locale clocks: 12-hour with a day period or 24-hour without |
| T2 | 12-hour, empty | digits and a/p |
hours, minutes, and the day period fill in order and commit a 24-hour PlainTime; letters and arrows toggle AM/PM |
typing hours, minutes, and a day period commits a 24-hour value |
| T3 | 12-hour | step | 12 AM is midnight and 12 PM is noon; hours wrap 12→1 without flipping the period; minutes wrap and Page steps by 15 | 12 AM and 12 PM map to midnight and noon; hours wrap within the clock |
| T4 | 24-hour, seconds | digits | two-digit hours wait for the second digit when it can fit; second granularity commits only after seconds; no hidden input without name |
24-hour typing accepts two-digit hours and seconds granularity requires seconds |
| T5 | min / max | commit / empty step | out-of-window times are invalid; placeholderValue seeds stepping from empty |
min and max mark times invalid; placeholderValue seeds empty stepping |
| T6 | disabled/read-only | keys | no edits are committed | disabled and read-only time fields block edits |
| T7 | imperative | expose / clock change | hourCycle, granularity, focus, setValue, clear; switching the clock re-renders the same time |
exposes hour cycle, granularity, and imperative editing |
| T8 | time model | helpers | PlainTime validation, comparison, truncation, and HH:MM[:SS] round-trips |
plain time helpers validate, compare, truncate, and round-trip ISO text |
| T9 | SSR/hydration | isolated requests | byte-identical segments and deterministic ids hydrate silently | renders byte-identical locale-ordered time segments across SSR requests, hydrates time segments with generated ids and no mismatches |
Root data adds data-hour-cycle (12/24) and data-granularity to the
DateField hooks, with data-vize-ui="time-field", time-field-segment, and
time-field-literal. The hidden input submits HH:MM, or HH:MM:SS for
second granularity.