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

GuidancePractices
DoChoose 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.
DoSet 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.
DoProvide a description or placeholder that hints at the expected format or purpose, like “Business hours: 9 AM – 5 PM”.
DoUse 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.
DoEnable hasClear when the field is optional, so users can easily remove a previously selected time.
Don'tDon’t use TimeInput for combined date-and-time selection — pair it with a separate DateInput instead.
Don'tDon’t hide the label — even when space is tight, keep the label visible or provide a description so the purpose is clear.

Anatomy

ElementDescription
Clock iconA leading clock icon that identifies the field as a time input.
Text inputrequiredThe editable text field where users type or see the formatted time.
Clear buttonA trailing button to reset the value, shown when hasClear is true and a value is set.
Status iconA trailing icon indicating error, warning, or success state.
SpinnerReplaces trailing content during loading to show an async action is in progress.

Import

ts
import {XDSTimeInput} from '@xds/core/TimeInput'

Props

PropTypeDescription
labelrequired
stringLabel text for the input (required for accessibility).
isLabelHidden
boolean (default: false)Visually hides the label while keeping it accessible to screen readers.
description
stringDescription 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
ISOTimeStringControlled time value in ISO format (HH:MM or HH:MM:SS).
onChange
(value: ISOTimeString | undefined) => voidCallback 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
ISOTimeStringMinimum selectable time in ISO format. Values outside the range are rejected.
max
ISOTimeStringMaximum 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
XDSInputStatusStatus indicator that colors the border and displays an icon. When a message is provided it is rendered below the input.
labelTooltip
stringTooltip text rendered as an info icon at the end of the label row.
xstyle
StyleXStylesStyleX 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}>
<XDSTimeInput
label="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}>
<XDSTimeInput
label="24-hour"
value={time24h as never}
onChange={setTime24h as never}
hourFormat="24h"
/>
<XDSTimeInput
label="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}>
<XDSTimeInput
label="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}>
<XDSTimeInput
label="Disabled field"
value={disabledVal as never}
onChange={setDisabledVal as never}
isDisabled
/>
<XDSTimeInput
label="Error message"
value={errorVal as never}
onChange={setErrorVal as never}
status={{type: 'error', message: 'Time must be during business hours'}}
/>
<XDSTimeInput
label="Warning message"
value={warningVal as never}
onChange={setWarningVal as never}
status={{type: 'warning', message: 'Early morning — are you sure?'}}
/>
<XDSTimeInput
label="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" />;
}