Skip to main content

TimeInput

Capture time input from user.

Submit feedback
github

Migration Information

For teams migrating from the V1 to V2 component, please refer to the migration guide for changes to the component.
Component Guide
import { TimeInput } from '@uhg-abyss/web/ui/TimeInput';
() => {
const [value, setValue] = useState('');
return (
<TimeInput
label="TimeInput Sandbox"
value={value}
onChange={setValue}
/>
);
};

Variants

Input with time picker

The default variant for TimeInput is an input field with a button to open a time picker.

Input only

Use the inputOnly prop when the time can be easily entered without a time picker.

Using useForm and FormProvider simplifies form management by providing out-of-the-box validation, form state handling, and performance optimizations, leveraging the power of react-hook-form.

useState

Using the useState hook gets values from the component state.

Format

Use the format prop to change the time format for the input. The possible values are '12' (the default) and '24'.

Display Properties

Label

Use the label prop to display a label above the input. To hide the input label, set hideLabel to true.

Use isRequired and isOptional for further customization.

Note: If using useForm, do not use isRequired. The same functionality can be achieved with required: true in validators.

Helper

Use the helper prop to display a help icon next to the label. Simply passing a string value will render the default helper, a Tooltip containing that string. The helper can be customized by passing in a node. It is recommended to use either a Tooltip or a Popover. See When should I use a Tooltip vs. a Popover? for more information on best practices regarding the two.

Subtext

Use the subText prop to display helpful information related to the input field. The prop accepts either a string or an object of the form:

{
text: string;
position: 'above' | 'below';
}

The position property determines where the subtext will be displayed in relation to the input field. The default value is 'below'.

Width

Use the width prop to set the width of the input field.

Left Element

Use the inputLeftElement prop to add an element inside the text input field. The recommended usage is for inserting icons. The prop accepts an object with the following properties:

  • element: The element to be displayed inside the input field.
  • description: An optional string that describes the purpose of the element for screen readers.

These are considered decorative and do not need to be exposed to screen readers. That said, please note that icons should not provide any information that is not also conveyed in a screen-readable way. For example, an exclamation mark (!) icon to indicate errors needs to be accompanied by aria-invalid.

If the icon is used to convey additional information, use the inputLeftElement.description prop to provide a description for screen readers.

Note: The recommended usage is when using the inputOnly prop.

Validation

Validators (useForm)

Form Compatibility
useState
useForm

Use the validators prop to set validation rules for the field when using useForm. See the examples below for implementation on various types of validation.

Note: The default error message when required is true is minimally acceptable for accessibility. It is highly recommended to customize it to be more specific to the use of the field and form.

Error message (useState)

Form Compatibility
useState
useForm

Use the errorMessage prop to display a custom error message below the input field when using useState.

Success message

Form Compatibility
useState
useForm

Use the successMessage prop to display a custom success message below the input field. To provide a single success message across all form input components using useForm/FormProvider, you can provide successMessage to FormProvider as shown here.

Highlighted

Form Compatibility
useState
useForm

Use the highlighted prop to enable a distinct background color when fields are required. To supply this across all form input components using useForm/FormProvider, you can provide highlighted to FormProvider as shown here.

Validation below menu

Form Compatibility
useState
useForm

Set the validationBelowMenu prop to true to relocate the error and success message validation to below the menu, when open.

The default is false and the validation message will always remain displayed below the selection container, even when the calendar is open.

Interactivity

Clearable

Set the isClearable prop to true to display a clear button in the input field. The optional onClear callback prop can be used to trigger additional actions when the clear button is clicked.

Disabled

Set the isDisabled prop to true to disable the input field, preventing user interaction. The input will still display the current value, but users cannot change it.

Enable outside scroll

Set the enableOutsideScroll prop to true to allow the page to be scrolled while the calendar is open. The default value is false.

Responsiveness

On screens 360px wide or smaller, the picker will be placed in a full-screen takeover instead of a popup. Resize the window and open the picker to see the change!

TimeInput Props

NameTypeDefaultRequiredDescription
className
string
--
CSS class name to apply to each element within the component
css
Abyss.CSSProperties | Partial<Record<`abyss-${T}`, Abyss.CSSProperties>>
--
Object containing CSS styling to apply; uses the classes listed in the "Integration" tab of the component's documentation

See CSS Prop Styling for more information
data-testid
string
--
Suffix used to create a unique ID used for automated testing

See Component Testing for more information
disableDefaultProviderProps
boolean
false
-
If set to true, the component will not use the DefaultPropsProvider values.

If you aren’t using the DefaultPropsProvider, this prop can be ignored.
enableOutsideScroll
boolean
false
-
If true, the page will remain scrollable when the popover is open
errorMessage
string | never
--
Error message to display for the input. Only used when not in a FormProvider.
errorMessage should not exist in useForm mode.
helper
React.ReactNode
--
Helper element next to label
hideLabel
boolean
false
-
If true, the label will be visually hidden
highlighted
boolean
false
-
If true, the input field will be highlighted
inputLeftElement
{ element: React.ReactNode; description?: string | undefined; }
--
Content to be displayed as a left element within the input (typically a IconSymbol)
inputOnly
boolean
false
-
If true, only the input field will be rendered without the picker button and popover time picker
isClearable
boolean
--
If true, the input will display a clear button
isDisabled
boolean
false
-
If true, the input will be disabled
isOptional
boolean
false
-
If true, the label will be appended with "(Optional)"
isRequired
boolean | never
--
Whether the input is required. Only used when not in a FormProvider.
isRequired should not exist in useForm mode.
label
string
-
The label for the input
model
never | string
--
model should not exist in useState mode.
Model name for form validation. Only used when in a FormProvider.
onApply
(currentTime: string) => void
--
Callback executed when the "Apply" button is clicked. Only shown when in mobile takeover mode.
onBlur
React.FocusEventHandler<HTMLInputElement>
--
Callback function executed when the input is blurred
onCancel
() => void
--
Callback executed when the "Cancel" button is clicked. Only shown when in mobile takeover mode.
onClear
() => void
--
Callback function executed when the input is cleared
onFocus
React.FocusEventHandler<HTMLInputElement>
--
Callback function executed when the input is focused
onPickerButtonClick
(() => void) | undefined
--
Callback executed when the picker button is clicked
openPosition
"default" | "top" | "bottom" | undefined
'default'
-
Determines where the TimePicker will open relative to the input
subText
string | { text: string; position: SubTextPosition; }
--
Additional descriptive text for the input
successMessage
string
--
Success message to display for the input
validationBelowMenu
boolean
false
-
If true, displays error and success validation messages below the menu
validators
never | RegisterOptions
--
validators should not exist in useState mode.
Validators for the input. Only used when in a FormProvider.
value
ValueType | never
--
The value of the input. Only used when not in a FormProvider.
value should not exist in useForm mode.

TimeInput Classes

Class NameDescription
.abyss-time-input-containerThe time input container
.abyss-time-input-input-containerThe container for the input fields
.abyss-time-input-hour-inputThe hour input
.abyss-time-input-minute-inputThe minute input
.abyss-time-input-am-pm-inputThe AM/PM input
.abyss-time-picker-rootRoot element of TimePicker
.abyss-time-picker-column-containerContainer for input columns (hour, minute, AM/PM)
.abyss-time-picker-separatorSeparator element between time inputs (colon)
.abyss-time-picker-hour-inputHour input field in TimePicker
.abyss-time-picker-minute-inputMinute input field in TimePicker
.abyss-time-picker-am-pm-inputAM/PM input field in TimePicker
.abyss-time-picker-increase-hours-buttonArrow button to increase hours
.abyss-time-picker-decrease-hours-buttonArrow button to decrease hours
.abyss-time-picker-increase-minutes-buttonArrow button to increase minutes
.abyss-time-picker-decrease-minutes-buttonArrow button to decrease minutes
.abyss-time-picker-increase-ampm-buttonArrow button to increase AM/PM
.abyss-time-picker-decrease-ampm-buttonArrow button to decrease AM/PM
.abyss-time-picker-arrow-buttonArrow button root element
.abyss-time-picker-arrow-button-iconArrow button icon element
.abyss-time-input-rootRoot element of PickerInput
.abyss-time-input-wrapperMain wrapper for PickerInput content
.abyss-time-input-label-wrapperWrapper for label and subtext
.abyss-time-input-labelLabel element for PickerInput
.abyss-time-input-sub-textSubtext element (above or below input)
.abyss-time-input-format-textFormat text element (e.g. date format)
.abyss-time-input-field-wrapperWrapper for the input field and button
.abyss-time-input-focus-wrapperFocus ring and input/clear button container
.abyss-time-input-input-wrapperWrapper for the input field and adjacent elements
.abyss-time-input-elements-containerContainer for input elements
.abyss-time-input-left-elementLeft element (e.g. icon) inside the input
.abyss-time-input-clearClear button for input
.abyss-time-input-picker-buttonPopover open button
.abyss-time-input-iconIcon inside the popover button
.abyss-time-input-descriptorsValidation or descriptor messages
.abyss-time-input-portal-containerPortal container for popover
.abyss-time-input-dismissable-layerDismissable layer for picker
.abyss-time-input-popover-wrapperPopover wrapper for picker content
.abyss-time-input-takeoverTakeover container for mobile view
.abyss-time-input-takeover-selection-display-containerContainer for the selection display in mobile takeover
.abyss-time-input-selection-display-textText element for the selection display
.abyss-time-input-takeover-button-containerContainer for buttons in mobile takeover
.abyss-time-input-apply-buttonApply button
.abyss-time-input-cancel-buttonCancel button
.abyss-time-input-selection-display-wrapperWrapper for the selection display
.abyss-time-input-selection-display-rootRoot element for the selection display
.abyss-time-input-selection-display-elements-containerContainer for the elements in the selection display
.abyss-time-input-selection-display-clearClear button for the selection display

TimeInput implements a simple group (<fieldset>) of three spin buttons for hours, minutes, and AM/PM. This makes the time picker dialog "redundant and unnecessary." To avoid the potential confusion and unnecessary redundant entry, the "Choose time" button does not receive keyboard focus.

Time Entry Keyboard Interactions Keyboard Interactions

KeyDescription
TabMoves focus to next TimeInput field, clear button or exits component
Shift + TabMoves focus to previous TimeInput field or exits component
Up ArrowIncrements current hour or minute field; toggles AM / PM
Down ArrowDecrements current hour or minute field; toggles AM / PM

Component Tokens

Note: Click on the token row to copy the token to your clipboard.

TimeInput Tokens

Token NameValue
time-input.color.border.selection-indicator
#E5E5E6
time-input.color.icon.default
#323334
time-input.color.icon.disabled
#7D7F81
time-input.color.icon.utility.active
#000000
time-input.color.icon.utility.hover
#323334
time-input.color.icon.utility.rest
#4B4D4F
time-input.color.surface.button.active
#E5E5E6
time-input.color.surface.button.hover
#F3F3F3
time-input.color.surface.button.rest
#FFFFFF
time-input.color.surface.picker-mobile
#FFFFFF
time-input.color.surface.selection-indicator.default
#F3F3F3
time-input.color.surface.selection-indicator.highlighted
#E5F8FB
time-input.color.text.sub-label
#4B4D4F
time-input.color.text.selection-indicator
#4B4D4F
time-input.border-radius.all.selection-indicator
4px
time-input.border-width.all.selection-indicator
1px
time-input.border-width.bottom.separator
1px
time-input.sizing.all.icon
20px
time-input.spacing.gap.horizontal.takeover-button-container
8px
time-input.spacing.gap.horizontal.selection-indicator
12px
time-input.spacing.gap.vertical.selection-indicator
8px
time-input.spacing.padding.all.takeover-button-container
16px
time-input.spacing.padding.all.takeover-header
16px
time-input.spacing.padding.bottom.takeover-input-container
24px
time-input.spacing.padding.horizontal.takeover-input-container
16px
time-input.spacing.padding.horizontal.selection-indicator
12px
time-input.spacing.padding.top.takeover-input-container
16px

TimePicker Tokens

Token NameValue
time-picker.color.border.container
#CBCCCD
time-picker.color.icon.arrow.active
#00184D
time-picker.color.icon.arrow.hover
#004BA0
time-picker.color.icon.arrow.rest
#002677
time-picker.color.surface.container
#FFFFFF
time-picker.border-radius.all.container
4px
time-picker.border-width.all.container
1px
time-picker.sizing.all.icon.arrow
24px
time-picker.spacing.padding.all.container
16px
time-picker.spacing.padding.horizontal.input-column-container
8px

Input Tokens

Token NameValue
input.color.surface.field.default
#FFFFFF
input.color.surface.field.highlighted
#E5F8FB
input.color.surface.field.disabled
#F3F3F3
input.color.border.field.rest
#4B4D4F
input.color.border.field.hover.default
#196ECF
input.color.border.field.hover.error
#990000
input.color.border.field.hover.success
#007000
input.color.border.field.active.default
#004BA0
input.color.border.field.active.error
#990000
input.color.border.field.active.success
#007000
input.color.text.input
#4B4D4F
input.color.text.hint
#4B4D4F
input.color.text.required
#990000
input.color.icon.utility.rest
#4B4D4F
input.color.icon.utility.hover
#323334
input.color.icon.utility.active
#000000
input.color.icon.content
#323334
input.border-radius.all.field
4px
input.border-width.all.field.default
1px
input.border-width.all.field.active
3px
input.sizing.all.icon
20px
input.spacing.gap.vertical.container
8px
input.spacing.gap.horizontal.field
12px
input.spacing.gap.horizontal.input-indicator
2px
input.spacing.gap.horizontal.prefix-input
2px
input.spacing.gap.horizontal.suffix-clear
2px
input.spacing.padding.all.focus-container
2px
input.spacing.padding.horizontal.field
12px
input.spacing.padding.left.field
12px
input.spacing.padding.right.focus-field
44px

PickerInput Tokens

Token NameValue
picker-input.color.border.popover
#CBCCCD
picker-input.color.border.takeover-separator
#E5E5E6
picker-input.color.icon.default
#323334
picker-input.color.icon.disabled
#7D7F81
picker-input.color.surface.button.active
#E5E5E6
picker-input.color.surface.button.disabled
#F3F3F3
picker-input.color.surface.button.hover
#F3F3F3
picker-input.color.surface.button.rest
#FFFFFF
picker-input.color.surface.popover
#FFFFFF
picker-input.color.surface.takeover-selection-display.default
#F3F3F3
picker-input.color.surface.takeover-selection-display.highlighted
#E5F8FB
picker-input.color.text.sub-label
#4B4D4F
picker-input.color.text.takeover-selection-display
#4B4D4F
picker-input.border-radius.all.popover
4px
picker-input.border-radius.all.takeover-selection-display
4px
picker-input.border-width.all.popover
1px
picker-input.border-width.all.takeover-selection-display
1px
picker-input.border-width.bottom.takeover-separator
1px
picker-input.sizing.all.icon
20px
picker-input.spacing.gap.horizontal.takeover-button-container
8px
picker-input.spacing.gap.horizontal.takeover-selection-display
12px
picker-input.spacing.gap.vertical.label
4px
picker-input.spacing.gap.vertical.popover
8px
picker-input.spacing.gap.vertical.takeover-selection-display
8px
picker-input.spacing.padding.all.takeover-header
16px
picker-input.spacing.padding.bottom.takeover-input-container
24px
picker-input.spacing.padding.horizontal.takeover-input-container
16px
picker-input.spacing.padding.horizontal.takeover-selection-display
12px
picker-input.spacing.padding.top.takeover-input-container
16px
picker-input.elevation.popover
0px 2px 4px -2px rgba(0,0,0,0.16)

Header Tokens

Token NameValue
input-header.color.text.label
#4B4D4F
input-header.color.text.hint
#4B4D4F
input-header.color.icon.info.rest
#196ECF
input-header.color.icon.info.hover
#004BA0
input-header.color.icon.info.active
#002677
input-header.sizing.all.icon
24px
input-header.spacing.gap.horizontal.container
4px
input-header.spacing.gap.horizontal.label
4px
input-header.spacing.gap.vertical.content
4px
input-header.spacing.padding.top.content
2px

Validation Tokens

Token NameValue
input-validation.color.surface.container
#FFFFFF
input-validation.color.text.error
#990000
input-validation.color.text.success
#007000
input-validation.color.icon.error
#990000
input-validation.color.icon.success
#007000
input-validation.sizing.all.icon
20px
input-validation.spacing.gap.horizontal.container
4px
Table of Contents