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

Last updated

Markdown is supported.

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

Add

npx @ava-ui/apogee add textarea

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

Usage

---
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:

Show code
<Textarea label="Small" size="small" placeholder="Small" />
<Textarea label="Medium" placeholder="Medium" />
<Textarea label="Large" size="large" placeholder="Large" />

Resize

Every resize value:

Grows as you type.

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

States

Tell us about yourself.

Show code
<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:

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