# Textarea

> A labeled multiline input, wired the same way as Input — label, hint, and error.

URL: https://apogee.avaui.dev/docs/textarea
Last updated: 2026-10-15

A labeled multiline input, wired the same way as Input — label, hint, and error.

Last updated October 15, 2026

```astro
<Textarea label="Message" hint="Markdown is supported." placeholder="Write something…" />
```

## Add

```sh
npx @ava-ui/apogee add textarea
```

Pulls in `Field` (label / hint / error scaffold).

## Usage

```astro
---
import Textarea from '@/components/apogee/Textarea/Textarea.astro'

<JsNote fallback="The box keeps its rows height and the resize handle.">
  `resize="auto"` grows the box to its content on input in browsers without `field-sizing: content` (Chromium has it natively).
</JsNote>
---
<Textarea label="Message" />
```

## Anatomy

`Textarea` renders a `Field` (label + hint/error scaffold) around a native `<textarea>`:

-   **Field** — label (with required asterisk), the control, then hint or error.
-   **Textarea** — the native `<textarea>`, sized by `size` and `rows`.

## API

`@composable` — exposed to Content Editors in AVA. Any other native `<textarea>` attribute (e.g. `placeholder`, `disabled`, `maxlength`, `name`) passes through.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `id` | `string` | auto-generated | Field id, shared by the label and the textarea. |
| `label` | `string` | — | Field label. |
| `hint` | `string` | — | Helper text below the field (hidden when `error` is set). |
| `error` | `string` | — | Error text; sets `aria-invalid` and swaps in for `hint`. |
| `rows` | `number` | `4` | Visible row count. |
| `value` | `string` | — | Initial text; the default slot works too. |
| `resize` | `'none' \| 'vertical' \| 'auto'` | `'vertical'` | Resize handle, or `auto` to grow with the content (`field-sizing: content`; a small island elsewhere). |
| `size` | `'small' \| 'medium' \| 'large' \| 'xlarge'` | `'medium'` | Padding and text size from the shared scale, 28 / 36 / 48 / 56px. |
| `variant` | `'outline' \| 'faded' \| 'ghost' \| 'headless'` | `'outline'` | The box style: bordered, tinted, bare, or no box at all. |
| `hasError` | `boolean` | `false` | Marks the field invalid (`aria-invalid`, critical border) without an `error` message. |
| `required` | `boolean` | `false` | Marks the field required (native `required` + label asterisk). |
| `class` | `string` | — | Extra classes on the `Field` wrapper, merged last. |

## Sizes

Every size:

```astro
<Textarea label="Small" size="small" placeholder="Small" />
<Textarea label="Medium" placeholder="Medium" />
<Textarea label="Large" size="large" placeholder="Large" />
```

## Resize

Every `resize` value:

```astro
<Textarea label="None" resize="none" rows={2} />
<Textarea label="Vertical" resize="vertical" rows={2} />
<Textarea label="Auto" resize="auto" rows={2} />
```

## States

```astro
<Textarea label="Disabled" disabled placeholder="Disabled" />
<Textarea label="Bio" error="Bio is required." />
<Textarea label="Bio" required hint="Tell us about yourself." />
```

-   **Hover** — border unchanged; no hover-specific style.
-   **Focus** — visible `focus-visible` ring (`--border-primary`).
-   **Disabled** — dimmed, not focusable, native `disabled`.
-   **Invalid** (`error` set) — `--background-critical` border, `aria-invalid="true"`, hint text replaced by the error message with `role="alert"`.

## Examples

More rows for longer content:

```astro
<Textarea label="Notes" rows={8} />
```

## Accessibility

-   Real `<label for>` / `<textarea id>` pairing via `Field`.
-   `aria-describedby` points to the hint or error paragraph; `aria-invalid` is set when `error` is present.
-   The error paragraph has `role="alert"` so it’s announced.
-   Focus ring is always visible on keyboard focus.

## Tokens

| Token | Used for |
| --- | --- |
| `--border-neutral` / `--background-page` / `--foreground-neutral` | Field border, fill, text |
| `--foreground-neutral-faded` | Placeholder + hint text |
| `--foreground-critical` | Invalid border + error text |
| `--border-primary` | Focus border |

## Do / Don’t

-   **Do** pair every `Textarea` with a `label` — placeholder text is not a label.
-   **Do** use `hint` for format guidance, `error` for validation failures — not both at once (error takes over).
-   **Don’t** disable a field without explaining why elsewhere on the page.
-   **Don’t** rely on `rows` alone for very long content — consider letting it grow or linking to a fuller editor.

## Content

-   Label is a short noun phrase, sentence case, no colon.
-   Error copy states what’s wrong and how to fix it (“Bio is required.”).
-   Hint text is one line, no ending period unless it’s a full sentence.

## Related

[

InputA labeled text field with hint/error messaging, wired for accessibility — plus a pure-CSS floating label.

](https://apogee.avaui.dev/docs/input)[

FieldThe labeled-field scaffold — label, control, and hint/error — wired for accessibility.

](https://apogee.avaui.dev/docs/field)[

RichTextEditorA small WYSIWYG editor — a formatting toolbar over a contenteditable region, synced to a hidden field for form submission.

](https://apogee.avaui.dev/docs/rich-text-editor)
