New

Textarea

A multi-line text input following the same conventions as Input — labels, helper text, error states, and three sizes.

Preview

Markdown is supported.

States

This field is required.

Sizes

SizeFont sizePadding
sm12px6px 10px
md13px8px 12px
lg15px10px 16px

Implementation

Textarea.tsx
tsx
import { Textarea } from "@/components/ui/Textarea";
import { useState } from "react";

// Basic with label
<Textarea label="Description" placeholder="Describe your project…" />

// Controlled
const [value, setValue] = useState("");
<Textarea
  label="Bio"
  helperText="Max 280 characters."
  value={value}
  onChange={(e) => setValue(e.target.value)}
  rows={3}
/>

// Error state
<Textarea
  label="Feedback"
  error="Feedback cannot be empty."
  defaultValue=""
/>

// Disabled
<Textarea
  label="Notes"
  defaultValue="These notes are read-only."
  disabled
/>

Props

All native <textarea> attributes are forwarded. Custom props are listed below.

PropTypeDefaultDescription
labelstringVisible label rendered above the textarea.
helperTextstringSupplemental hint rendered below the textarea.
errorstringError message. Replaces helperText and applies error styling.
inputSize"sm" | "md" | "lg""md"Controls padding and font size. Does not constrain height — use rows or CSS for that.
rowsnumber4Number of visible text rows. The textarea is vertically resizable by the user.

ARIA roles

ElementRoleKey attributes
Textareatextbox (implicit)aria-multiline='true', aria-label / aria-labelledby, aria-invalid, aria-describedby, aria-required

Keyboard

KeyAction
All text editing keysStandard text editing — type, delete, navigate the cursor
TabMove focus out of the textarea to the next focusable element
Shift+TabMove focus to the previous focusable element

Accessibility

  • Built on a native <textarea> element — keyboard focusable and screen-reader accessible.
  • The label prop renders a <label> element associated via htmlFor.
  • Error messages appear as visible text below the field; pair with aria-describedby for screen readers.
  • Vertical resize is enabled by default (resize-y) — do not disable it as it aids users who need larger input areas.
  • Character count limits should be communicated with a visible counter and aria-live for screen reader updates.