EXEPERTAI LAB

Research alpha

Time Machine
EXEPERTAI LAB
GALLERY / COLLECTION
← Browse Astryx gallery
TextArea·component·@astryxdesign/core

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.

Open in Playground @astryxdesign/core/TextArea

Showcases and examples

5 documented examples

Text Area

A text area with placeholder text.

Preview loads on approachPreview loads on approach
Exact source · text-area-showcase
// Copyright (c) Meta Platforms, Inc. and affiliates.

'use client';

import {useState} from 'react';
import {TextArea} from '@astryxdesign/core/TextArea';

export default function TextAreaShowcase() {
  const [value, setValue] = useState('');
  return (
    <div style={{width: 400}}>
      <TextArea
        label="Description"
        value={value}
        onChange={setValue}
        placeholder="Enter a description..."
      />
    </div>
  );
}

Usage

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.

  • 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 using TextArea for short, single-line values like names or emails; use TextInput instead.
  • Don't rely solely on placeholder text to communicate the purpose of the field; placeholders disappear on focus and are not accessible labels.
  • 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.
  • 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.

Typed props

PropType and behavior
refReact.Ref<HTMLTextAreaElement>
Ref forwarded to the underlying <textarea> element.
labelstring · required
Label text for the textarea. Always rendered for accessibility.
valuestring · required
Current value of the textarea.
onChange(value: string, e: ChangeEvent<HTMLTextAreaElement>) => void
Callback 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.
isLabelHiddenboolean · default false
Visually hides the label while keeping it accessible to screen readers.
descriptionstring
Helper text displayed between the label and textarea.
isOptionalboolean · default false
Displays an "Optional" indicator next to the label. Mutually exclusive with isRequired.
isRequiredboolean · default false
Displays a "Required" indicator next to the label and sets aria-required. Mutually exclusive with isOptional.
isDisabledboolean · default false
Disables the textarea, preventing interaction.
isReadOnlyboolean · default false
Makes 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.
disabledMessagestring
Explains 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.
isLoadingboolean · default false
Puts the textarea in a loading state, showing a spinner inside the input.
placeholderstring
Placeholder text shown when the textarea is empty.
rowsnumber · default 3
Number of visible text rows.
maxLengthnumber
Maximum 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' · default '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.
labelTooltipstring
Tooltip text displayed in an info icon at the end of the label.
startIconIconType
Icon component rendered inside the leading edge of the textarea wrapper. See astryx docs icons for valid semantic names.
hasSpellCheckboolean · default true
Enables or disables browser spell checking.
hasAutoFocusboolean · default false
Automatically focuses the textarea on mount.
size'sm' | 'md' | 'lg' · default 'md'
Size of the textarea, affecting internal padding. Height is controlled by rows, not size.
onPaste(e: ClipboardEvent<HTMLTextAreaElement>) => void
Callback fired when content is pasted into the textarea.
htmlNamestring
HTML name attribute for the textarea element, useful for form submissions.
widthSizeValue
Width 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>) => void
Callback fired when the textarea receives focus.
onBlur(e: FocusEvent<HTMLTextAreaElement>) => void
Callback fired when the textarea loses focus.
autoCompletestring
The native autocomplete attribute, forwarded to the textarea unchanged. Does not affect the controlled value.
xstyleStyleXStyles
StyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value, not an inline style object like style={{}}.

Anatomy

Label · required

Text identifying the multi-line field.

Description · optional

Helper text between the label and the input.

Input container · required

Painted boundary containing the text area and its overlays.

Text area · required

Multi-line control that displays and edits the value.

Placeholder · optional

Hint text shown inside the empty text area.

Start icon · optional

Astryx Icon rendered at the start when startIcon is a semantic name or icon component.

Custom start content · optional

Caller-provided ReactNode rendered at the start instead of an Astryx Icon.

Spinner · optional

Loading indicator shown at the end of the input container.

Status icon · optional

Error, warning, or success icon shown inside the input.

Character counter · optional

Current and maximum character counts shown inside the input container.

Field status message · optional

Attached or detached error, warning, or success message associated with the field.

Tooltip status message · optional

Tooltip surface presenting the status message for the tooltip variant.

Theming

Targets

astryx-text-area

Visual props: size, status

States: disabled, readonly

astryx-text-area-control
astryx-text-area-counter
astryx-textarea

Visual props: size, status

States: disabled, readonly

Deprecated; use text-area.

Variables

--_textarea-inline-padding · private

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)

Derived properties

paddingInline

Uses --_textarea-inline-padding.

Replaces the source property rule.