A 24-hour segmented time field that matches DateInput. Direct numeric entry uses the same replacement, focus, validation, disabled, and empty-value behavior.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| time | Date | null | Yes | - | Controlled time value; null represents an empty field |
| onTimeChange | (time: Date | null) => void | Yes | - | Called after valid entry or clearing the field |
| label | string | No | - | Visible and accessible field label |
| aria-label | string | No | "Time" | Accessible label when no visible label is used |
| name | string | No | - | Submits a 24-hour HH:MM value through a hidden input |
| disabled | boolean | No | false | Disables time entry |
| readOnly | boolean | No | false | Prevents changes while retaining the displayed value |
| required | boolean | No | false | Marks both time segments as required |
| aria-invalid | boolean | No | false | Applies the shared invalid-field treatment |
| jss | JSS | No | - | Styles the field wrapper |
Provide either label or aria-label so the grouped time segments have an accessible name.
const [time, setTime] = useState<Date | null>(new Date());
<TimeInput label="Start time" time={time} onTimeChange={setTime} />;
Focus selects a complete segment, so normal typing replaces the existing hour or minute. Completing the hour advances focus to the minute.
const [time, setTime] = useState<Date | null>(null);
<TimeInput aria-label="End time" time={time} onTimeChange={setTime} />;
Completed values outside 00:00 through 23:59 receive the invalid-field treatment and are not committed.