Skip to content

Textarea

<Textarea> is a multi-line <textarea> styled with the design tokens. Pass autosize for chat / agent prompt UIs that should grow with content.

import from "@na/ui/components/textarea" ▶ Open in Storybook packages/ui/src/components/textarea.tsx

When to use

  • Any free-form, multi-line input — descriptions, comments, prompts.
  • Chat composer / agent prompt input (with autosize).

Don’t use Textarea for: single-line input (Input), rich text (RichText — not yet shipped), or huge bodies of text where the user would benefit from a code editor.

Default

Fixed height — the user resizes manually if they need more room.

<Textarea placeholder="Add a description…" rows={3} />

Autosize

Pass autosize for a textarea that grows with content. Defaults: minRows={2}, maxRows={8}.

<Textarea autosize placeholder="Type a message…" />
// Tune the bounds:
<Textarea autosize={{ minRows: 1, maxRows: 12 }} />

Disabled / read-only

<Textarea disabled defaultValue="Disabled" />
<Textarea readOnly defaultValue="Read-only" />

Invalid

Sets aria-invalid on the textarea — the design tokens take care of the destructive ring.

<Textarea aria-invalid={Boolean(fieldState.error)} {...field} />

API

Prop Type Default Description
autosize boolean | { minRows?: number; maxRows?: number } false Enable autosize. Pass true for defaults (2 / 8) or an object to tune.
rows number Initial fixed height (ignored when autosize is set).
disabled boolean false Native disabled.
readOnly boolean false Native read-only.
aria-invalid boolean false Triggers the destructive ring.
...rest TextareaHTMLAttributes All native textarea attributes (placeholder, value, onChange, defaultValue, name, etc.).

Design guidelines

✓ Do

  • Use autosize for chat / prompt inputs. The growth feels right; fixed height feels cramped.
  • Set a sensible maxRows — the textarea should scroll internally beyond it, not push the page.
  • Pair with FormError for validation messages.

✗ Don't

  • Use Textarea for single-line input — that is Input.
  • Disable the textarea while waiting for a response. Use a Button mutation state instead and let the user keep typing.
  • Use autosize on a form field where you expect a single line. The growth then becomes a bug.

Accessibility

  • Native <textarea> semantics — works with all assistive tech out of the box.
  • Pair with a <Label> (or aria-labelledby) — the textarea on its own has no name.
  • For autosize: the user’s keyboard cursor stays in place as the height changes, so screen-reader announcement of the value is unaffected.
  • Input — Single-line.
  • Form — Form-state integration with react-hook-form.
  • FormError — Inline validation message.

▶ Open Textarea stories in Storybook