TimeInput
TimeInput accepts a 24-hour time without opening a picker. Choose it when typing a precise value is the efficient path; use TimePicker when people need to browse a set of available times.
Examples
A normalised 24-hour time
People can type 9, 0930 or 9:5. Blur or Enter parses a valid entry, normalises it to HH:mm
and calls onChange with that value.
Bounds and increments
min and max clamp committed and stepped values. Arrow keys and the steppers move by step;
hold Shift with an arrow key to move by one hour.
Translated spoken controls
Use labels to replace the English stepper names and to provide the spoken aria-valuetext for a
selected time. Unspecified labels keep their English defaults.
When to use
Use TimeInput when a person knows or can efficiently type a single 24-hour time.
Reach for something else when:
- The available times need to be browsed from a list — use TimePicker, which is designed for that selection flow.
- Only a date is needed — use a date-specific control rather than accepting an ambiguous time.
- A duration is being entered — use separate duration fields or a control that names units instead of treating it as a clock time.
Accessibility
- Renders a text input with
role="spinbutton", numeric input mode andaria-valuemin,aria-valuemaxandaria-valuenowin minutes. A suppliedlabelis connected throughhtmlFor. - The two mouse stepper buttons are removed from the tab order; keyboard users adjust the focused input with ArrowUp and ArrowDown. Shift plus an arrow moves one hour.
- A selected value receives
aria-valuetextfromlabels.valueText; uselabelsto translate the default English stepper names and spoken value. - Invalid text is deliberately preserved on blur or Enter, marked invalid, and does not call
onChange. A valid value is normalised and committed; an intentional empty value commitsnull. errorreplaceshint, is connected througharia-describedby, and setsaria-invalid.invalidcan set invalid styling without a visible error message.
API and code
| Name | Type | Required | Description |
|---|---|---|---|
label | string | — | Label rendered above the input and connected with htmlFor. |
hint | string | — | Helper text rendered below the input. Replaced by error when present. |
error | string | — | Error message that enables error styling and replaces hint. |
value | string | null | — | Controlled 24-hour HH:mm value, or null for no selected time. |
defaultValue | string | — | Initial 24-hour HH:mm value in uncontrolled mode. |
onChange | (time: string | null) => void | — | Called with a normalized HH:mm value, or null after the field is cleared. |
step | number | — | Minutes added or subtracted by the steppers and Arrow keys. Default: 15. |
min | string | — | Inclusive HH:mm lower limit. Values below it are clamped. |
max | string | — | Inclusive HH:mm upper limit. Values above it are clamped. |
size | 'sm' | 'md' | 'lg' | — | Control height. Default: "md". |
invalid | boolean | — | Enables invalid styling and aria-invalid without an error message. |
labels | TimeInputLabels | — | Translatable accessible labels, merged over the English defaults. |
disabled | boolean | — | Disables the input and steppers. |
x-data="lyraTimeInput({ … })"
| Option | Type | Required | Description |
|---|---|---|---|
defaultValue | string | — | Initial 24-hour HH:mm value, or no selection when omitted. |
step | number | — | Minutes added or subtracted by steppers and Arrow keys. Default: `15`. |
min | string | — | Inclusive 24-hour HH:mm lower limit. |
max | string | — | Inclusive 24-hour HH:mm upper limit. |
invalid | boolean | — | Enables consumer-driven invalid styling and `aria-invalid`. |
valueText | (hours: number, minutes: number) => string | — | Spoken value for a selected time. |
Without React, use the same structure and implement parsing, clamping and keyboard behaviour yourself:
<div class="lyra-field">
<label class="lyra-label" for="start-time">Start time</label>
<span class="lyra-timeinput">
<input
class="lyra-input"
id="start-time"
type="text"
role="spinbutton"
inputmode="numeric"
aria-valuemin="0"
aria-valuemax="1439"
aria-valuenow="570"
aria-valuetext="9 hours and 30 minutes"
value="09:30"
/>
<span class="lyra-timeinput__steppers">
<button class="lyra-timeinput__step" type="button" tabindex="-1" aria-label="Later">▲</button>
<button class="lyra-timeinput__step" type="button" tabindex="-1" aria-label="Earlier">
▼
</button>
</span>
</span>
<span class="lyra-hint">Enter a 24-hour time.</span>
</div><lyra:time-input> Generated from lyra-ds/blade v0.10.0.
The behavior comes from lyraTimeInput() — install @lyra-ds/alpine and see the HTML + Alpine tab.
| Prop | Default | Required | Example values |
|---|---|---|---|
label | null | — | Start time |
hint | null | — | Use 24-hour time |
error | null | — | Invalid Invalid time |
value | null | — | — |
defaultValue | null | — | — |
step | 15 | — | — |
min | null | — | — |
max | null | — | — |
size | 'md' | — | lg sm |
invalid | false | — | — |
labels | [] | — | — |
disabled | false | — | — |
<lyra:time-input
name="start_time"
label="Start time"
default-value="09:00"
:step="15"
min="08:00"
max="18:00"
size="md"
/>