# Textarea

## Overview

The textarea component is a multi-line text control for longer freeform responses such as notes, comments, and descriptions.

The component pattern uses a native `<label>` that wraps a native `<textarea>`, so the control can be styled without requiring a classed wrapper.

## When to use

Use a textarea for longer free-form content that may span multiple lines.

## When not to use

Do not use a textarea for a short, single-line response; use an input.

## Usage

```html
<label>
  <span data-role="label">Notes</span>
  <textarea
    rows="4"
    required
    minlength="20"
    maxlength="280"
    placeholder="Add details"
    aria-describedby="notes-feedback"
  ></textarea>
  <span id="notes-feedback" data-role="feedback">
    <span id="notes-error" data-role="message" data-invalid="Enter at least 20 characters."></span>
    <span id="notes-limit" data-role="limit">280 character max</span>
  </span>
</label>
```

Use this component when the user needs to enter content that can span multiple lines.

Use an input instead when the expected response is short and single-line.

The label should remain visible above the field, and the placeholder should act as an example rather than replacing the label.

The field should use native `<label>` and `<textarea>` elements so the control keeps browser form behavior, keyboard support, and expected text editing behavior.

Wrap the visible label text in a `[data-role="label"]` element so required fields can render the red asterisk immediately after the label text.

When a character limit is shown, place a `[data-role="feedback"]` element directly after the textarea. Use `[data-role="message"]` for validation text and `[data-role="limit"]` for a static character-limit hint. Pair those with native constraints such as `required`, `minlength`, or `maxlength`, and associate the textarea with that supporting text using `aria-describedby`.

## Behavior

Covered by [Playwright behavior tests](../../tests/e2e/forms-inputs.spec.js).

- TXA-001: The field uses shared control padding, border, and typography tokens, with a textarea radius that defaults to half the shared control radius.
- TXA-002: Placeholder text stays muted while entered text uses the default foreground color.
- TXA-003: Focus must remain clearly visible for keyboard users.
- TXA-004: The field allows vertical resizing so users can expand the control for longer responses.
- TXA-005: Comfortable and compact density should come from the layout theme tokens rather than textarea-specific theme branches.
- TXA-006: Validation feedback should appear only after user interaction by using `:user-invalid` rather than showing errors on initial page load.
- TXA-007: Character limits should be expressed as static supporting text unless JavaScript is intentionally introduced for a live count.
## Accessibility

- Use a native `<label>` so the field stays explicitly named.
- If the label does not wrap the textarea, associate them with matching `for` and `id` attributes.
- Do not rely on placeholder text as the only field description.
- Keep focus indication and text contrast strong enough to remain visible in normal use.
- When showing a counter or error text, keep that supporting text in the DOM and associate it with the textarea through `aria-describedby`.
- Preserve native textarea behavior rather than replacing it with a scripted text surface unless the behavior truly requires it.

## Variables

| Variable | Type | Description |
| --- | --- | --- |
| `--textarea-border-color` | `<color>` | Sets the textarea border color, including error overrides; change it when multiline fields need neutral or validation-state emphasis. |
| `--textarea-border-radius` | `<length>` | Sets textarea corner radius; change it when multiline fields should be sharper or softer than single-line inputs. |
| `--textarea-color-error-strong` | `<color>` | Sets --textarea-color-error-strong so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--textarea-color-focus-ring` | `<color>` | Sets --textarea-color-focus-ring so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--textarea-color-primary` | `<color>` | Sets --textarea-color-primary so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--textarea-color-text` | `<color>` | Sets --textarea-color-text so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--textarea-color-text-accent` | `<color>` | Sets --textarea-color-text-accent so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--textarea-color-text-subtle` | `<color>` | Sets --textarea-color-text-subtle so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--textarea-control-border-width` | `<length>` | Sets --textarea-control-border-width so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--textarea-control-gap` | `<length>` | Sets --textarea-control-gap so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--textarea-control-padding-block` | `<length>` | Sets --textarea-control-padding-block so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--textarea-control-padding-inline` | `<length>` | Sets --textarea-control-padding-inline so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--textarea-focus-ring-size` | `<length>` | Sets --textarea-focus-ring-size so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--textarea-font-size` | `<length>` | Sets --textarea-font-size so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--textarea-font-size-caption` | `<length>` | Sets --textarea-font-size-caption so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--textarea-line-height` | `<number>` | Sets --textarea-line-height so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--textarea-message-color` | `<color>` | Sets helper and validation message text color for textareas; change it when field messaging should move between subtle and error emphasis. |
| `--textarea-space-inline` | `<length>` | Sets --textarea-space-inline so the component can default to shared theme or layout tokens while exposing an overrideable component API. |

## Depends On

- `--color-border-subtle`
- `--color-error-strong`
- `--color-focus-ring`
- `--color-primary`
- `--color-text`
- `--color-text-accent`
- `--color-text-subtle`
- `--font-line-height-body`
- `--font-size`
- `--font-size-caption`
- `--layout-control-border-width`
- `--layout-control-gap`
- `--layout-control-padding-block`
- `--layout-control-padding-inline`
- `--layout-control-radius`
- `--layout-focus-ring-size`
- `--layout-space-inline`
