JGuang

TextInput

TextInput · Astryx

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

TextInput

TextInput collects short-form text like names, emails, or search queries. Use it for single-line values where the expected input is brief. Pair it with validation status to guide users through required or formatted fields.

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.

Text Input

TextInput collects short-form text like names, emails, or search queries. Use it for single-line values where the expected input is brief. Pair it with validation status to guide users through required or formatted fields.

PropTypeDefaultDescription
type'text' | 'password' | 'email''text'The HTML input type.
label *stringLabel text for the input: always rendered for accessibility.
value *stringCurrent value of the input.
onChange(value: string, e: ChangeEvent<HTMLInputElement>) => voidCallback fired when the input value changes.
changeAction(value: string, e: ChangeEvent<HTMLInputElement>) => void | Promise<void>Async action fired after onChange (if not prevented). Triggers optimistic update and shows a loading spinner while pending.
size'sm' | 'md' | 'lg''md'Size variant of the input.
isLabelHiddenbooleanfalseVisually hides the label while keeping it accessible to screen readers.
descriptionstringDescription text displayed between the label and input.
isOptionalbooleanfalseDisplays an "Optional" indicator next to the label. Mutually exclusive with isRequired.
isRequiredbooleanfalseDisplays a "Required" indicator next to the label and sets aria-required. Mutually exclusive with isOptional.
onEnter() => voidCallback fired when the user presses the Enter key. IME-safe: Enter used to commit a Japanese/Chinese/Korean conversion does not fire it.
onKeyDown(e: KeyboardEvent<HTMLInputElement>) => voidCallback fired on keydown events on the input.
isDisabledbooleanfalseDisables the input, preventing interaction and dimming the element.
isReadOnlybooleanfalseMakes the input read-only: the value is shown at full opacity and still submits with the form, but cannot be edited. Unlike isDisabled, a read-only input is not dimmed and stays in the tab order. isDisabled takes precedence when both are set.
disabledMessagestringExplains why the input is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the input focusable via aria-disabled (the field becomes read-only). Use this instead of wrapping a disabled TextInput in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.
isLoadingbooleanfalsePuts the input in a loading state, showing a spinner and setting aria-busy.
placeholderstringPlaceholder text shown when the input is empty.
labelTooltipstringTooltip text displayed in an info icon at the end of the label.
startIconIconTypeSVG icon component displayed at the start of the input. See astryx docs icons for valid semantic names.
status{type: 'error' | 'warning' | 'success', message?: string}Validation status: applies a colored border and status icon. If message is provided, displays a floating message below the input. Error type also sets aria-invalid.
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.
hasClearbooleanfalseShows a clear (×) button when the input has a value. Clicking it clears the value and returns focus to the input.
hasAutoFocusbooleanfalseAutomatically focuses the input on mount.
htmlNamestringThe HTML name attribute for the input, useful for form submissions.
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. Without a width the field can shrink with its row, so a filter bar never overflows; use <HStack wrap="wrap"> when the controls should move to a second line instead.
autoCompletestringThe native autocomplete attribute, forwarded to the input unchanged. Does not affect the controlled value.
containerXstyleStyleXStylesStyleX styles for the field container (label, control, and status together). No effect inside InputGroup (style the InputGroup instead) or in a horizontal-labels FormLayout. Root xstyle, className, and style are not accepted.
containerClassNamestringClass name for the field container. Same targeting as containerXstyle.
containerStyleCSSPropertiesInline styles for the field container. Same targeting as containerXstyle.
controlXstyleStyleXStylesStyleX styles for the visual control box: the element that paints the border and background and holds icons and end controls. Never the native input.
controlClassNamestringClass name for the visual control box.
controlStyleCSSPropertiesInline styles for the visual control box.

Usage guidance

  • Always provide a visible label so users know what the field is for. Only hide the label when surrounding context makes it obvious, like a search bar with a magnifying-glass icon.
  • Use validation status with a message to explain what went wrong: "Email must include @" is better than just turning the border red.
  • Size the input to match the expected content length so users can gauge how much to type: small for zip codes, medium for names, large for URLs.
  • Add a clear button for search and filter inputs so users can quickly reset without selecting all text.
  • Avoid: Don't use placeholder text as a replacement for a label; placeholders disappear on focus and are not reliably read by screen readers.
  • Avoid: Don't use TextInput for multi-line content like comments or descriptions; use TextArea instead.
  • Avoid: Don't mark every field as required; only flag mandatory fields so users are not overwhelmed by validation errors.
  • Avoid: Don't wrap a disabled TextInput in Tooltip to explain why it's disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.

Theming API

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

Anatomy

  • Label: Text that identifies the field. Always rendered for accessibility even when visually hidden.
  • Description: Helper text between the label and the input that provides additional context or formatting hints.
  • Start icon: A leading icon inside the input that hints at the expected content, like a magnifying glass for search.
  • Placeholder: Hint text shown when the input is empty. Disappears on focus.
  • Clear button: A trailing × button that resets the value and returns focus to the input.
  • Spinner: Loading indicator that appears during async actions like server-side validation.
  • Status icon: A trailing icon (error, warning, or success) that communicates validation state.

Examples

  • Text Input:
  • TextInput — Icon: Inputs with a leading icon that hints at the expected content. Use when the icon helps users identify the field faster, like a lock for passwords or an envelope for email.
  • TextInput — Search: Search input with a hidden label, start icon, and clear button. Use for toolbar and header search bars where the icon provides sufficient context.
  • TextInput — Sizes: Small, medium, and large inputs side by side. Use small in dense UIs like table filters, medium for most forms, and large for prominent single-field pages.
  • TextInput — States: Error, warning, and success validation states with status messages. Use to show users what went wrong and how to fix it.
  • TextInput — Status variant: The statusVariant prop controls whether the status message is attached to the bordered input (default, overlapping directly below) or detached from it (floating below as a separate element with spacing).
  • TextInput — Types: Text, password, and email types plus field-level features: tooltip, required, optional, description, disabled, and loading.

Complete example dependencies

Some examples import optional icons. The per-example install command in the examples list identifies exactly what that example needs. For all examples on this page:

npm install @heroicons/react@2.2.0