Textarea

Multi-line input. Same fill, border, inner shadow, hover overlay, and focus ring as Input.

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-md border border-input bg-input-fill shadow-input-inner",
    "transition-[box-shadow,border-color,background-image] duration-150 ease-out",
    "hover:[background-image:linear-gradient(rgba(0,0,0,0.03),rgba(0,0,0,0.03))]",
    "dark:hover:[background-image:linear-gradient(rgba(255,255,255,0.03),rgba(255,255,255,0.03))]",
    "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 !shadow-none resize-none
               hover:!bg-none focus-visible:!shadow-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