JGuang

TimeInput

TimeInput · Astryx

Preview
npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0

TimeInput

TimeInput uses a browser/OS time picker on coarse pointers by default and Astryx's typed field on fine pointers. It converts values to a standard format and supports arrow-key adjustment on the typed surface. Use it in forms, scheduling flows, or any interface where users need to select a specific time.

Installation

npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0

Requires React 19+, base CSS and a Theme provider. See Setup.

Time Input

TimeInput uses a browser/OS time picker on coarse pointers by default and Astryx's typed field on fine pointers. It converts values to a standard format and supports arrow-key adjustment on the typed surface. Use it in forms, scheduling flows, or any interface where users need to select a specific time.

PropTypeDefaultDescription
label *stringLabel text for the input (required for accessibility).
isLabelHiddenbooleanfalseVisually hides the label while keeping it accessible to screen readers.
descriptionstringDescription text displayed between the label and input.
isOptionalbooleanfalseShows an "(optional)" indicator next to the label. Mutually exclusive with isRequired.
isRequiredbooleanfalseMarks the field as required and sets aria-required. Mutually exclusive with isOptional.
isDisabledbooleanfalseDisables the input and suppresses interactions.
disabledMessagestringExplains why the input is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the field focusable via aria-disabled (activation stays blocked). Use this instead of wrapping a disabled TimeInput in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.
valueISOTimeStringControlled 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.
isLoadingbooleanfalsePuts the input into a loading state, displaying a spinner.
minISOTimeStringMinimum selectable time in ISO format. Values outside the range are rejected.
maxISOTimeStringMaximum selectable time in ISO format. Values outside the range are rejected.
hasSecondsbooleanfalseIncludes seconds in the time display and parsing.
hasClearbooleanfalseShows a clear button when a value is set and the input is not disabled.
hourFormat'12h' | '24h''12h'Controls the display format. '12h' shows AM/PM (e.g. '2:30 PM'); '24h' uses 24-hour notation (e.g. '14:30').
incrementnumber1Number of minutes to add or subtract when the user presses the up or down arrow key.
presentation'text-input' | 'popover' | 'bottom-sheet' | 'native' | 'adaptive-bottom-sheet' | 'adaptive-native''adaptive-native'Which surface selects the time. 'adaptive-native' (the default) uses Astryx's typed field on a fine pointer and the browser/OS input type=time on a coarse pointer — except hasSeconds or increment other than 1, which retain the typed field because iOS has no seconds wheel and treats step as validation rather than picker cadence; 'native' always uses the browser/OS control with no Astryx fallback; 'adaptive-bottom-sheet' uses the typed field on a fine pointer and Astryx's bottom-sheet time wheels on a coarse pointer; 'bottom-sheet' forces the wheels on every pointer; 'text-input' (like 'popover', which has no distinct TimeInput surface) keeps only the typed field. Native mode forwards min/max and enforces them on commit. hourFormat formats the closed value; the open OS picker follows the device locale.
nativePicker'touch' | 'always' | 'never''touch'Deprecated: use presentation ('touch' = 'adaptive-native', 'always' = 'native', 'never' = 'text-input'). Still works exactly as released; presentation wins when both are set.
placeholderstring'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''md'Controls the height of the input element.
status{type: 'warning' | 'error' | 'success', message?: string}Status indicator that colors the border and displays an icon. When a message is provided it is rendered below the input.
statusVariant'attached' | 'detached' | 'tooltip''attached'How the status message is placed relative to the input. attached overlaps directly below the input (bordered treatment); detached floats below as a separate element with spacing; tooltip hides the message box and surfaces it in a tooltip on the status icon.
labelTooltipstringTooltip text rendered as an info icon at the end of the label row.
widthSizeValueWidth of the field (number = pixels, string used as-is, e.g. "100%"). Sizes the whole field (label, control, and status) so they stay aligned.
containerXstyleStyleXStylesStyleX styles for the Field box around the label, control, and status. containerClassName and containerStyle take a class name and inline styles for the same box. No effect (development warning) where no Field box renders: inside InputGroup (style the group) and in a horizontal-labels FormLayout.
controlXstyleStyleXStylesStyleX styles for the visual control box: the bordered element that holds the text, icons, and end controls, never the native input. controlClassName and controlStyle take a class name and inline styles for the same box. Replaces root xstyle, className, and style, which this component does not accept.

Usage guidance

  • Base props such as ref, id, data-, aria-, and DOM event handlers go to the time input, the element that is focused and announced. A DOM handler runs after TimeInput's own handler for the same event and still receives events it handled (including ones it called preventDefault on), so it cannot cancel built-in behavior.
  • 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.
  • 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.
  • Provide a description or placeholder that hints at the expected format or purpose, like "Business hours: 9 AM – 5 PM".
  • 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.
  • Enable hasClear when the field is optional, so users can remove a previously selected time.
  • Place TimeInput inside InputGroup when the time needs a single-line prefix or suffix addon, like a start/end label or timezone marker.
  • Avoid: Don't use TimeInput for combined date-and-time selection; pair it with a separate DateInput instead.
  • Avoid: Don't hide the label; even when space is tight, keep the label visible or provide a description so the purpose is clear.
  • Avoid: Wrap a disabled TimeInput in Tooltip to explain why it is disabled; disabled triggers swallow the hover events the wrapper needs. Use the disabledMessage prop instead.

Theming API

{
  "targets": [
    {
      "className": "astryx-time-input",
      "visualProps": [
        "size",
        "status"
      ],
      "states": [
        "disabled"
      ]
    }
  ]
}

Anatomy

  • Clock icon: A leading clock icon that identifies the field and opens the browser/OS picker in native mode.
  • Time control: A real input type=time in native modes, or Astryx's editable text field for fine pointers, presentation="text-input", seconds, and custom increments.
  • 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.

Examples

  • Time Input: A time input that uses the browser/OS picker on touch by default and Astryx typed entry on fine pointers.
  • TimeInput — Constrained: Time inputs with min/max constraints limiting selection to specific windows. Use to prevent out-of-bounds selections for appointments, reservations, or shift scheduling.
  • TimeInput — Formats: 12-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.
  • TimeInput — Increment: Time input with a custom step increment. Arrow keys jump by the specified interval (e.g. 15 minutes) for quick slot-based scheduling.
  • TimeInput — States: Default, disabled, error, warning, and success states. Use status messages to give users clear feedback about their time selection.