TimeField
Overview
A segmented time input that renders individually editable hour, minute, and optional second and day-period segments while submitting a native form value. Use it whenever a user must enter a time fast and precisely — scheduling, booking, time-window filtering, or any form that needs a validated time. For a date with a time, use SDateField with granularity: 'minute'; for a range, prefer STimeRangeField.
Usage
Features
- 🕐 Segmented editing — hour, minute, and optional second and day-period segments, each an editable
role="spinbutton" - 🎚 Controlled / uncontrolled —
v-model/defaultValuefor the value, backed byuseControllableState - 🕛 12/24-hour cycle —
hourCycleswitches betweenAM/PMand 24-hour display per locale, with day-period segment editing - ⌨️ Full keyboard support — digit typing with auto-advance,
ArrowUp/ArrowDownincrement/decrement,ArrowLeft/ArrowRightsegment navigation with RTL reversal - ⛓ Time validation —
minValue/maxValue/isTimeUnavailablemark the rootdata-invalid - 📝 Native form value — a visually hidden
input[type="time"]carries the ISO value to its owning form - ⚙️ Granularity & step —
granularity(hour/minute/second) andstepcontrol which segments render and the increment per arrow - 🧩 Composable slots —
leading/trailingplace content around the segments - 🚫 Disabled / readonly — both states block editing and render proper
data-*/aria-*attributes
Component family
STimeField— the styled wrapper that forwards props to the Aria compact and injectsdateFieldVariants(shared withSDateField) classesTimeFieldCompact(Aria) — data-driven composition ofTimeFieldRoot+ oneTimeFieldInputper segment, plusleading/trailingslots; import from@vean/aria/time-fieldfor unstyled usageTimeFieldRoot/TimeFieldInput(Aria) — the state owner (segment values, validation, hidden input, focus management) and a single editable segment bound to the shareduseDateFieldcomposable
Demos
Basic
Value: Sat Jan 01 2000 09:30:00 GMT+0000 (Coordinated Universal Time)
Custom Styling
API
Aria Layer
4TimeField
Props
| Prop | Type | Default | Description |
|---|---|---|---|
class | ClassValue | — | Additional class names applied to the root element. |
size | ThemeSize | — | Visual size of the component. |
ui | Partial<TimeFieldUi> | — | Per-slot class overrides for the component. |
inputProps | DateFieldInputProps | — | Properties forwarded to the input element. |
defaultValue | Date | — | Default value for the time field. |
modelValue | Date | — | Current model value. |
defaultPlaceholder | Date | — | Default placeholder. |
placeholder | Date | — | Placeholder. |
granularity | TimeGranularity | — | Granularity. |
maxValue | Date | — | Max value. |
minValue | Date | — | Min value. |
isTimeUnavailable | TimeMatcher | — | Whether the time is unavailable. |
disabled | boolean | — | Whether the component is disabled. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
dir | Direction | — | Reading direction of the component. |
id | string | — | Id. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
readonly | boolean | — | Whether the component is readonly. |
step | DateStep | — | Step. |
locale | string | — | Locale. |
hourCycle | HourCycle | — | Hour cycle. |
hideTimeZone | boolean | — | Whether hide time zone. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | Date | undefined | Emitted when the model value changes. |
update:placeholder | Date | Emitted when the placeholder value changes. |
Slots
| Slot Name | Parameters | Description |
|---|---|---|
leading | — | Content rendered before the time segments. |
trailing | — | Content rendered after the time segments. |
TimeFieldCompact
Props
| Prop | Type | Default | Description |
|---|---|---|---|
inputProps | DateFieldInputProps | — | Properties forwarded to the input element. |
defaultValue | Date | — | Default value for the time field. |
modelValue | Date | — | Current model value. |
defaultPlaceholder | Date | — | Default placeholder. |
placeholder | Date | — | Placeholder. |
granularity | TimeGranularity | — | Granularity. |
maxValue | Date | — | Max value. |
minValue | Date | — | Min value. |
isTimeUnavailable | TimeMatcher | — | Whether the time is unavailable. |
disabled | boolean | — | Whether the component is disabled. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
dir | Direction | — | Reading direction of the component. |
id | string | — | Id. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
readonly | boolean | — | Whether the component is readonly. |
step | DateStep | — | Step. |
locale | string | — | Locale. |
hourCycle | HourCycle | — | Hour cycle. |
hideTimeZone | boolean | — | Whether hide time zone. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | Date | undefined | Emitted when the model value changes. |
update:placeholder | Date | Emitted when the placeholder value changes. |
Slots
| Slot Name | Parameters | Description |
|---|---|---|
leading | — | Content rendered before the time segments. |
trailing | — | Content rendered after the time segments. |
TimeFieldInput
TimeFieldRoot
Props
| Prop | Type | Default | Description |
|---|---|---|---|
defaultValue | Date | — | Default value for the time field. |
modelValue | Date | — | Current model value. |
defaultPlaceholder | Date | — | Default placeholder. |
placeholder | Date | — | Placeholder. |
granularity | TimeGranularity | — | Granularity. |
maxValue | Date | — | Max value. |
minValue | Date | — | Min value. |
isTimeUnavailable | TimeMatcher | — | Whether the time is unavailable. |
disabled | boolean | — | Whether the component is disabled. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
dir | Direction | — | Reading direction of the component. |
id | string | — | Id. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
readonly | boolean | — | Whether the component is readonly. |
step | DateStep | — | Step. |
locale | string | — | Locale. |
hourCycle | HourCycle | — | Hour cycle. |
hideTimeZone | boolean | — | Whether hide time zone. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | Date | undefined | Emitted when the model value changes. |
update:placeholder | Date | Emitted when the placeholder value changes. |
Slots
| Slot Name | Parameters | Description |
|---|---|---|
default | TimeFieldRootSlotProps | — |
Notes
Architecture and benchmark differences
TimeFieldRoot owns the TimeValue via useControllableState, keeps segmentValues as a shallowRef, and runs validation through isInvalid. Each TimeFieldInput binds the same useDateField composable used by the date-field family for per-part keydown logic; TimeFieldCompact iterates the segments produced by createContent and renders one input each, with leading/trailing slots around them. Focus movement is handled by the root’s moveFocus, mapping the physical arrow key from dir so RTL swaps ArrowLeft/ArrowRight. Most benchmark libraries ship a plain text input or select-based picker; the segmented spinbutton pattern with keyboard increment/typing and the Aria/styled split are the differentiators.
| Capability | VeanUI | Ant Design | Element Plus | Mantine | Naive UI | shadcn |
|---|---|---|---|---|---|---|
| Aria/styled split | ✅ | — | — | — | — | — |
| Segmented editable segments | ✅ | — | — | — | — | — |
| Controlled / uncontrolled | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| 12/24-hour cycle | ✅ | ✅ | ✅ | — | ✅ | — |
| Keyboard increment/typing | ✅ | — | — | — | — | — |
| Segment navigation + RTL | ✅ | — | — | — | — | — |
| Range validation | ✅ | ✅ | — | — | — | — |
isTimeUnavailable | ✅ | — | — | — | — | — |
| Granularity (second) | ✅ | ✅ | ✅ | — | ✅ | — |
| Configurable step | ✅ | ✅ | ✅ | — | — | — |
| Native form value | ✅ | — | — | ✅ | — | — |
leading / trailing slots | ✅ | — | — | — | — | — |
| Disabled / readonly | ✅ | ✅ | ✅ | ✅ | ✅ | — |
Cautions
- The value is a
TimeValue— a nativeDatewhose hour/minute/second parts are meaningful (the date part is normalized), not astring. Use it with the other date-family components. defaultValueis only read on mount — usev-modelfor external control.- When the value is empty the segments display the placeholder time (derived from
defaultValue/defaultPlaceholderor the current time) — the submitted form value is still empty until the user types. granularitydefaults to'minute'; pass'second'for seconds segments or'hour'to hide the minute segment.hourCycle(12/24) controls the day-period segment and the accessible hour range; leave it unset to follow the locale.- Time validation marks the root
data-invalidbut never clamps the value — clear or correct it in the parent.
FAQ
How do I edit a time with the keyboard?
Tab into the field and type digits — after the segment fills it advances automatically. ArrowUp/ArrowDown increment or decrement the focused segment, ArrowLeft/ArrowRight move between segments (reversed in RTL), and Backspace clears digits. On a 12-hour cycle a/p toggles AM/PM.
How do I show seconds or hide the minute segment?
Pass granularity: 'second' to render hour, minute, and second segments, or granularity: 'hour' to render only the hour segment.
How do I switch between 12-hour and 24-hour display?
Pass hourCycle: 12 or hourCycle: 24. Leave it unset to follow the active locale.
How do I restrict the selectable time?
Pass minValue/maxValue — times outside are marked data-invalid and rejected. isTimeUnavailable accepts a predicate for arbitrary exclusions.
How is STimeField different from SDateField with granularity: 'minute'?
STimeField is a pure time input — it never renders date segments. SDateField with a time granularity renders the full date and time together (for example 2026/04/19 14:30) and accepts a { date, time } value.