Textarea

Multi-line free text — comments, messages, descriptions, prompts. Reach for it when input can run past one line or wrap; use Input for single-line values (name, email, search) and Combobox/Select when the value comes from a known set. Flat surface — white fill, 10% border, rounded (6px), no inner shadow — matching Input's fill, hover overlay, and focus ring, with an 80px min-height and resize-y. Use invalid for failed validation, readOnly for non-editable-but-readable content, and disabled when the field is inactive.

Basic

<Textarea placeholder="Type your message here…" />

With an action bar

// Pattern: Textarea + an action bar below. The whole wrapper — textarea and
// action bar — shares one border + hover + focus + invalid state. The inner
// Textarea strips its own chrome so only the wrapper renders them.
//
//   LEFT:  context (model picker, tool toggles, scope)
//   RIGHT: actions (upload, mic, and the primary Send button)

<div
  className={cn(
    "rounded border border-input bg-input-fill",
    "transition-[box-shadow,border-color,background-image] duration-150 ease-out",
    "hover:[background-image:linear-gradient(var(--surface-hover-overlay),var(--surface-hover-overlay))]",
    "focus-within:shadow-ring-primary-input focus-within:border-focus",
    "has-[[aria-invalid=true]]:border-[var(--border-destructive-50)]",
    "has-[[aria-invalid=true]]:focus-within:shadow-ring-destructive-input"
  )}
>
  <Textarea
    placeholder="Type your message here…"
    className="!border-0 !bg-transparent resize-none
               hover:!bg-none focus-visible:!border-transparent"
  />
  {/* All controls share h-8 so the bar reads as a single row. */}
  <div className="flex items-center justify-between gap-2 px-2 pb-2 ">
    <div className="flex items-center gap-1">
      <Button variant="outline" className="text-sm" iconTrailing={<Chevron />}>Claude Opus 4.6</Button>
      <Button variant="ghost" className="text-sm" iconLeading={<Plus />}>Add</Button>
    </div>
    <div className="flex items-center gap-1">
      <IconButton variant="ghost" aria-label="Attach file"><Paperclip /></IconButton>
      <IconButton variant="ghost" aria-label="Record"><Mic /></IconButton>
      <IconButton variant="primary" aria-label="Send"><ArrowUp /></IconButton>
    </div>
  </div>
</div>
Rule: the action bar is two button groups — left for context (model picker, mode, scope) and right for actions (upload, mic, then the primary Send button). The Send button is the only Primary in the group and sits at the far right.

States

<>
  <Textarea placeholder="Default" />
  <Textarea disabled defaultValue="cannot edit" />
  <Textarea readOnly defaultValue="read only" />
  <Textarea invalid defaultValue="too short" />
</>

Props

PropTypeDefault
invalidbooleanfalse
disabledbooleanfalse
readOnlybooleanfalse
…restTextareaHTMLAttributes

Source

packages/react/src/components/textarea.tsx · Figma node 2819:31165