XDSTimeInput@xds/core · TimeInput
Preview coming soon
Usage
TimeInput lets users enter a time of day and converts it to a standard format. It also allows users to adjust times using the arrow keys. Use it in forms, scheduling flows, or any interface where users need to select a specific time.Best practices
| Guidance | Practices |
|---|---|
| Do | Choose the hour format (12h or 24h) that matches your audience’s locale — 12-hour with AM/PM for US-centric UIs, 24-hour for international or technical contexts. |
| Do | Set min and max constraints when the context has a valid range, like business hours or event windows, so users cannot submit an out-of-bounds time. |
| Do | Provide a description or placeholder that hints at the expected format or purpose, like “Business hours: 9 AM – 5 PM”. |
| Do | Use the status prop to surface validation errors inline — show a message like “Time must be during business hours” so users know exactly what to fix. |
| Do | Enable hasClear when the field is optional, so users can easily remove a previously selected time. |
| Don't | Don’t use TimeInput for combined date-and-time selection — pair it with a separate DateInput instead. |
| Don't | Don’t hide the label — even when space is tight, keep the label visible or provide a description so the purpose is clear. |
Anatomy
| Element | Description | |
|---|---|---|
| Clock icon | A leading clock icon that identifies the field as a time input. | |
| Text input | required | The editable text field where users type or see the formatted time. |
| Clear button | A trailing button to reset the value, shown when hasClear is true and a value is set. | |
| Status icon | A trailing icon indicating error, warning, or success state. | |
| Spinner | Replaces trailing content during loading to show an async action is in progress. |
Import
tsimport {XDSTimeInput} from '@xds/core/TimeInput'
Props
| Prop | Type | Description |
|---|---|---|
labelrequired | string | Label text for the input (required for accessibility). |
isLabelHidden | boolean (default: false) | Visually hides the label while keeping it accessible to screen readers. |
description | string | Description text displayed between the label and input. |
isOptional | boolean (default: false) | Shows an "(optional)" indicator next to the label. Mutually exclusive with isRequired. |
isRequired | boolean (default: false) | Marks the field as required and sets aria-required. Mutually exclusive with isOptional. |
isDisabled | boolean (default: false) | Disables the input and suppresses interactions. |
value | ISOTimeString | Controlled time value in ISO format (HH:MM or HH:MM:SS). |
onChange | (value: ISOTimeString | undefined) => void | Callback fired when the time changes. Receives undefined when the input is cleared. |
changeAction | (value: ISOTimeString | undefined) => void | Promise<void> | Async action fired after onChange. Wrapped in a React transition to provide optimistic UI; triggers the loading spinner while pending. |
isLoading | boolean (default: false) | Puts the input into a loading state, displaying a spinner. |
min | ISOTimeString | Minimum selectable time in ISO format. Values outside the range are rejected. |
max | ISOTimeString | Maximum selectable time in ISO format. Values outside the range are rejected. |
hasSeconds | boolean (default: false) | Includes seconds in the time display and parsing. |
hasClear | boolean (default: false) | Shows a clear button when a value is set and the input is not disabled. |
hourFormat | '12h' | '24h' (default: '12h') | Controls the display format. '12h' shows AM/PM (e.g. '2:30 PM'); '24h' uses 24-hour notation (e.g. '14:30'). |
increment | number (default: 1) | Number of minutes to add or subtract when the user presses the up or down arrow key. |
placeholder | string (default: 'Select a time') | Placeholder text shown when no time is selected. When the input is focused and empty, a format hint overrides this text. |
size | 'sm' | 'md' | 'lg' (default: 'md') | Controls the height of the input element. |
status | XDSInputStatus | Status indicator that colors the border and displays an icon. When a message is provided it is rendered below the input. |
labelTooltip | string | Tooltip text rendered as an info icon at the end of the label row. |
xstyle | StyleXStyles | StyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value — not an inline style object like style={{}}. |
Examples
Common configurations, variations, and states.TimeInput — ConstrainedTime inputs with min/max constraints limiting selection to specific windows. Use to prevent out-of-bounds selections for appointments, reservations, or shift scheduling.
tsx'use client';import {useState} from 'react';import {XDSTimeInput} from '@xds/core/TimeInput';import {XDSStack} from '@xds/core/Layout';export default function TimeInputConstrained() {const [evening, setEvening] = useState(undefined);return (<XDSStack direction="vertical" gap={3}><XDSTimeInputlabel="Dinner reservation"min={'17:00' as never}max={'22:00' as never}description="Evening seating: 5 PM – 10 PM"placeholder="Select reservation time"value={evening as never}onChange={setEvening as never}hasClear/></XDSStack>);}
TimeInput — Formats12-hour, 24-hour, and seconds formats side by side. Use 12h for US-centric UIs, 24h for international or technical contexts, and seconds for precise timing.
tsx'use client';import {useState} from 'react';import {XDSTimeInput} from '@xds/core/TimeInput';import {XDSStack} from '@xds/core/Layout';import {XDSText} from '@xds/core/Text';export default function TimeInputFormats() {const [time24h, setTime24h] = useState('14:30');const [timeSec, setTimeSec] = useState('14:30:45');return (<XDSStack direction="vertical" gap={4}><XDSText type="supporting" color="secondary">Format variations for different contexts</XDSText><XDSStack direction="vertical" gap={3}><XDSTimeInputlabel="24-hour"value={time24h as never}onChange={setTime24h as never}hourFormat="24h"/><XDSTimeInputlabel="With seconds"value={timeSec as never}onChange={setTimeSec as never}hasSeconds/></XDSStack></XDSStack>);}
TimeInput — IncrementTime input with a custom step increment. Arrow keys jump by the specified interval (e.g. 15 minutes) for quick slot-based scheduling.
tsx'use client';import {useState} from 'react';import {XDSTimeInput} from '@xds/core/TimeInput';import {XDSStack} from '@xds/core/Layout';export default function TimeInputIncrement() {const [slot, setSlot] = useState('09:00');return (<XDSStack direction="vertical" gap={3}><XDSTimeInputlabel="Appointment slot"increment={15}description="Use arrow keys to change by 15 minutes"value={slot as never}onChange={setSlot as never}hasClear/></XDSStack>);}
TimeInput — StatesDefault, disabled, error, warning, and success states. Use status messages to give users clear feedback about their time selection.
tsx'use client';import {useState} from 'react';import {XDSTimeInput} from '@xds/core/TimeInput';import {XDSStack} from '@xds/core/Layout';export default function TimeInputStates() {const [disabledVal, setDisabledVal] = useState('10:00');const [errorVal, setErrorVal] = useState('22:00');const [warningVal, setWarningVal] = useState('07:00');const [successVal, setSuccessVal] = useState('10:00');return (<XDSStack direction="vertical" gap={3}><XDSTimeInputlabel="Disabled field"value={disabledVal as never}onChange={setDisabledVal as never}isDisabled/><XDSTimeInputlabel="Error message"value={errorVal as never}onChange={setErrorVal as never}status={{type: 'error', message: 'Time must be during business hours'}}/><XDSTimeInputlabel="Warning message"value={warningVal as never}onChange={setWarningVal as never}status={{type: 'warning', message: 'Early morning — are you sure?'}}/><XDSTimeInputlabel="Success message"value={successVal as never}onChange={setSuccessVal as never}status={{type: 'success', message: 'Time slot is available'}}/></XDSStack>);}
Showcase source
tsx'use client';import {XDSTimeInput} from '@xds/core/TimeInput';export default function TimeInputShowcase() {return <XDSTimeInput label="Time" placeholder="Select a time" />;}