# TextArea

> Slug: `text-area` · Category: Form Controls

## When to use

- Multi-line free text: comments, feedback, descriptions, addresses, notes.
- Whenever the user might type more than one line.

## When NOT to use

- Single-line text — use `TextField`.
- Rich-text editing — Arrow does not include a WYSIWYG; use a third-party editor.
- Code entry — use a code editor component.

## Variants & decision tree

| Need | Prop |
|---|---|
| Standard | (default) |
| Smaller form factor | `isCompact` |
| Helper text below | `supportingText` |
| Inline error | `errorMessage` |

## States

Empty (label centered, then floats on focus/value), focused, filled, disabled, read-only, error, compact.

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `id` | `string` | — | Required. Textarea id. |
| `label` | `string` | — | Required. Floating label. |
| `value` / `defaultValue` | `string` | — | Controlled / uncontrolled. |
| `onChange` | `ChangeEventHandler<HTMLTextAreaElement>` | — | Standard handler. |
| `errorMessage` | `string` | — | Inline validation error. |
| `supportingText` | `string` | — | Helper text. |
| `isCompact` | `boolean` | `false` | Smaller padding/height. |
| `inverse` | `boolean` | `false` | Dark-background styling. |
| `disabled` | `boolean` | `false` | Disable. |
| `readOnly` | `boolean` | `false` | Read-only. |
| `required` | `boolean` | `false` | Required marker. |
| `maxLength` | `number` | — | Max characters. |
| `rows` | `number` | — | Initial visible rows. |
| `name` | `string` | — | Form submission name. |
| `formId` | `string` | — | Associates with a form by id. |

## Usage examples

```tsx
// Default
<TextArea id="bio" name="bio" label="Bio" supportingText="Max 500 characters" maxLength={500} />

// Controlled
const [comment, setComment] = useState('');
<TextArea
  id="comment"
  name="comment"
  label="Comments"
  value={comment}
  onChange={(e) => setComment(e.target.value)}
/>

// Error and compact
<TextArea id="note" label="Short note" isCompact errorMessage="Required" />
```

## Composition

Use inside `<form>` with other inputs. Pair `maxLength` with `supportingText` like "0 / 500" if you implement a counter.

## Accessibility

`id` and `label` are required. The component renders the `<label htmlFor={id}>` — do not wrap it manually. `errorMessage` wires `aria-invalid` and `aria-describedby`. `disabled` and `readOnly` follow native textarea semantics.

## Do / Don't

- DO use `isCompact` when stacking many short-input textareas.
- DO set `maxLength` for length-bound fields and surface a counter in `supportingText`.
- DON'T use TextArea for single-line input — use TextField.
- DON'T disable resize via inline styles; respect Arrow's CSS handling.
