# TextArea

- Page: https://jiguang132.com/resources/astryx/docs/text-area
- Resource: Astryx (https://jiguang132.com/resources/astryx.md)
- All guides: https://jiguang132.com/resources/astryx/docs.md

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

```bash
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](/resources/astryx/docs/getting-started).

## 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.

| Prop | Type | Default | Description |
|---|---|---|---|
| ref | React.Ref<HTMLTextAreaElement> |  | Ref forwarded to the underlying <textarea> element. |
| label * | string |  | Label text for the textarea. Always rendered for accessibility. |
| value * | string |  | 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. |
| isLabelHidden | boolean | false | Visually hides the label while keeping it accessible to screen readers. |
| description | string |  | Helper text displayed between the label and textarea. |
| isOptional | boolean | false | Displays an "Optional" indicator next to the label. Mutually exclusive with isRequired. |
| isRequired | boolean | false | Displays a "Required" indicator next to the label and sets aria-required. Mutually exclusive with isOptional. |
| isDisabled | boolean | false | Disables the textarea, preventing interaction. |
| isReadOnly | boolean | 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. |
| disabledMessage | string |  | 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. |
| isLoading | boolean | false | Puts the textarea in a loading state, showing a spinner inside the input. |
| placeholder | string |  | Placeholder text shown when the textarea is empty. |
| rows | number | 3 | Number of visible text rows. |
| maxLength | number |  | 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' | '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. |
| labelTooltip | string |  | Tooltip text displayed in an info icon at the end of the label. |
| startIcon | IconType |  | Icon component rendered inside the leading edge of the textarea wrapper. See `astryx docs icons` for valid semantic names. |
| hasSpellCheck | boolean | true | Enables or disables browser spell checking. |
| hasAutoFocus | boolean | false | Automatically 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>) => void |  | Callback fired when content is pasted into the textarea. |
| htmlName | string |  | HTML name attribute for the textarea element, useful for form submissions. |
| width | SizeValue |  | 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. |
| autoComplete | string |  | The native autocomplete attribute, forwarded to the textarea unchanged. Does not affect the controlled value. |
| containerXstyle | StyleXStyles |  | StyleX 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. |
| containerClassName | string |  | Class name for the field container. Same targeting as `containerXstyle`. |
| containerStyle | CSSProperties |  | Inline styles for the field container. Same targeting as `containerXstyle`. |
| controlXstyle | StyleXStyles |  | StyleX styles for the visual control box: the element that paints the border and background and holds icons and end controls. Never the native input. |
| controlClassName | string |  | Class name for the visual control box. |
| controlStyle | CSSProperties |  | Inline 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

```json
{
  "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:

```bash
npm install @heroicons/react@2.2.0
```

---

Index of all JGuang resources: https://jiguang132.com/llms.txt
