JGuang

TextArea

TextArea · Astryx

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

TextArea

TextArea is a multi-line text input for collecting longer-form content like comments, descriptions, or messages. Use it when the expected input spans multiple lines. For shorter, single-line values, use TextInput.

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 Area

TextArea is a multi-line text input for collecting longer-form content like comments, descriptions, or messages. Use it when the expected input spans multiple lines. For shorter, single-line values, use TextInput.

PropTypeDefaultDescription
refReact.Ref<HTMLTextAreaElement>Ref forwarded to the underlying <textarea> element.
label *stringLabel text for the textarea. Always rendered for accessibility.
value *stringCurrent value of the textarea.
onChange(value: string, e: ChangeEvent<HTMLTextAreaElement>) => voidCallback fired when the textarea value changes.
changeAction(value: string, e: ChangeEvent<HTMLTextAreaElement>) => void | Promise<void>Async action fired after onChange inside a React transition. Enables optimistic updates via useOptimistic.
isLabelHiddenbooleanfalseVisually hides the label while keeping it accessible to screen readers.
descriptionstringHelper text displayed between the label and textarea.
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.
isDisabledbooleanfalseDisables the textarea, preventing interaction.
isReadOnlybooleanfalseMakes the textarea read-only: the value is shown at full opacity and still submits with the form, but cannot be edited. Unlike isDisabled, a read-only textarea is not dimmed and stays in the tab order. isDisabled takes precedence when both are set.
disabledMessagestringExplains why the textarea is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the textarea focusable via aria-disabled (the field becomes read-only). Use this instead of wrapping a disabled TextArea in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.
isLoadingbooleanfalsePuts the textarea in a loading state, showing a spinner inside the input.
placeholderstringPlaceholder text shown when the textarea is empty.
rowsnumber3Number of visible text rows.
maxLengthnumberMaximum number of characters allowed, counted as user-perceived characters: an emoji or flag sequence counts as one. When set, a character counter (current/max) is displayed inside the input container, anchored to the bottom-right beneath the text. Does not enforce the limit natively; when exceeded the counter turns red and shows a warning icon (a non-color cue), and screen-reader users hear the remaining/over-limit count announced. Consumers validating the limit should count with characterCount (exported from the package) so enforcement matches the displayed count.
status{ type: 'warning' | 'error' | 'success'; message?: string }Status indicator that applies a colored border and icon. An optional message is displayed in a floating box below the textarea.
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 displayed in an info icon at the end of the label.
startIconIconTypeIcon component rendered inside the leading edge of the textarea wrapper. See astryx docs icons for valid semantic names.
hasSpellCheckbooleantrueEnables or disables browser spell checking.
hasAutoFocusbooleanfalseAutomatically focuses the textarea on mount.
size'sm' | 'md' | 'lg''md'Size of the textarea, affecting internal padding. Height is controlled by rows, not size.
onPaste(e: ClipboardEvent<HTMLTextAreaElement>) => voidCallback fired when content is pasted into the textarea.
htmlNamestringHTML name attribute for the textarea element, 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.
onFocus(e: FocusEvent<HTMLTextAreaElement>) => voidCallback fired when the textarea receives focus.
onBlur(e: FocusEvent<HTMLTextAreaElement>) => voidCallback fired when the textarea loses focus.
autoCompletestringThe native autocomplete attribute, forwarded to the textarea 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

  • Provide a visible label so users know what to enter. If the label must be hidden, set isLabelHidden with a descriptive label for screen readers.
  • Set maxLength with a character counter when there is a defined limit; it helps users stay within bounds before they submit.
  • Use the status prop to surface validation feedback inline: show success when input is valid, warning for soft limits, and error for hard failures.
  • Add a description or placeholder to clarify expected content, like "Describe the issue in detail," but never rely on placeholder alone as the only label.
  • Avoid: Avoid using TextArea for short, single-line values like names or emails; use TextInput instead.
  • Avoid: Don't rely solely on placeholder text to communicate the purpose of the field; placeholders disappear on focus and are not accessible labels.
  • Avoid: Don't show a status message without also setting the status type; the colored border and icon are what draw the user's attention to the message.
  • Avoid: Don't wrap a disabled TextArea 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-area",
      "visualProps": [
        "size",
        "status"
      ],
      "states": [
        "disabled",
        "readonly"
      ]
    },
    {
      "className": "astryx-text-area-control"
    },
    {
      "className": "astryx-text-area-counter"
    }
  ],
  "vars": [
    {
      "name": "--_textarea-inline-padding",
      "description": "Inline padding of the textarea's text. The wrapper stays flush (padding: 0) so the native resize grip sits in the true corner; this var carries the inset on the inner <textarea>, and the start icon, status/spinner, and character counter align to it.",
      "default": "var(--spacing-2)",
      "private": true
    }
  ],
  "derived": [
    {
      "property": "paddingInline",
      "vars": [
        "--_textarea-inline-padding"
      ],
      "replaces": true
    }
  ]
}

Anatomy

  • Label: Text identifying the multi-line field.
  • Description: Helper text between the label and the input.
  • Input container: Painted boundary containing the text area and its overlays.
  • Text area: Multi-line control that displays and edits the value.
  • Placeholder: Hint text shown inside the empty text area.
  • Start icon: Astryx Icon rendered at the start when startIcon is a semantic name or icon component.
  • Custom start content: Caller-provided ReactNode rendered at the start instead of an Astryx Icon.
  • Spinner: Loading indicator shown at the end of the input container.
  • Status icon: Error, warning, or success icon shown inside the input.
  • Character counter: Current and maximum character counts shown inside the input container.
  • Field status message: Attached or detached error, warning, or success message associated with the field.
  • Tooltip status message: Tooltip surface presenting the status message for the tooltip variant.

Examples

  • Text Area: A text area with placeholder text.
  • TextArea — Character Count: Textareas with maxLength and a live character counter. The counter turns red when the limit is exceeded.
  • TextArea — States: Required, disabled, and loading textareas side by side. Shows the interactive states the component supports.
  • TextArea — Validation: All three status variants (error, warning, and success) with status messages, plus error without a message. Use to show inline validation feedback as the user types.
  • TextArea — Icon: Textareas with a leading icon that hints at the expected content, like a chat bubble for messages or a pencil for notes.

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