For the complete documentation index, see llms.txt. Markdown variants are available by appending .md to any URL or sending an Accept: text/markdown header. An agent skill is available at /.well-known/agent-skills/site-skill.md.
Home

Textarea

A multi-line text input with the same border, focus ring, and invalid state as Input.

Max 500 characters
This field is required.
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";

export const TextareaDemo = () => (
    <div className="flex flex-col gap-6">
      {/* Default */}
      <Textarea placeholder="Write something…" />
      {/* With label */}
      <div className="flex flex-col gap-1.5">
        <Label htmlFor="ta-bio">Bio</Label>
        <Textarea id="ta-bio" placeholder="Tell us about yourself" className="min-h-24" />
      </div>
      {/* With label and helper + button */}
      <div className="flex flex-col gap-1.5">
        <Label htmlFor="ta-message">Message</Label>
        <Textarea id="ta-message" placeholder="Your message…" className="min-h-28" />
        <div className="flex items-center justify-between">
          <span className="text-muted-foreground text-xs">Max 500 characters</span>
          <Button size="sm">Send</Button>
        </div>
      </div>
      {/* Disabled */}
      <div className="flex flex-col gap-1.5">
        <Label htmlFor="ta-disabled">Disabled</Label>
        <Textarea id="ta-disabled" defaultValue="This field is read-only." disabled />
      </div>
      {/* Invalid */}
      <div className="flex flex-col gap-1.5">
        <Label htmlFor="ta-invalid">Feedback</Label>
        <Textarea id="ta-invalid" placeholder="Describe the issue…" aria-invalid />
        <span className="text-destructive text-xs">This field is required.</span>
      </div>
    </div>
  );

With label

<div className="flex flex-col gap-1.5">
  <Label htmlFor="bio">Bio</Label>
  <Textarea id="bio" placeholder="Tell us about yourself" />
</div>

Custom height

Override the default min-h-16 via className.

<Textarea className="min-h-32" placeholder="Long form content…" />

Auto-resize

Use the native rows attribute or a library like react-textarea-autosize for dynamic height.

<Textarea rows={3} />

Disabled

<Textarea disabled defaultValue="Read-only content." />

Invalid

Set aria-invalid to trigger the destructive ring.

<Textarea aria-invalid placeholder="Describe the issue…" />

Props

Textarea accepts all native <textarea> props.

PropTypeDefaultDescription
placeholderstring—Placeholder text
disabledbooleanfalseDisables interaction
aria-invalidbooleanfalseApplies destructive ring
rowsnumber—Fixed row count
classNamestring—Override min-h or add utilities

Usage

import { Textarea } from "@/components/ui/textarea";
 
<Textarea placeholder="Write something…" />

Specs

# Mint — Textarea Specs
 
## Component
- name: textarea
- file: registry/mint/textarea.tsx
- installs to: components/ui/textarea.tsx
- dependencies: none
- registryDependencies: none
 
## What is it
A multi-line text input that shares the same visual language as Input: identical
border, focus ring, invalid state, and disabled treatment. Use it whenever a
single-line Input is insufficient — forms, comments, descriptions, or any free-
form text entry. Prefer Input when content is expected to stay on one line.
 
## Visual identity
Transparent background with a subtle border gives it a lightweight, flat feel
consistent with Input. The 1.25rem radius and 3px focus ring match all other
form fields in Mint, ensuring visual consistency across form layouts.
 
## Design tokens
--input: oklch(0.88 0.04 155 / 60%) / oklch(0.32 0.05 155 / 40%)                        — border colour (border-input)
--ring: oklch(0.5 0.14 155) / oklch(0.62 0.15 155)                            — focus ring (focus-visible:border-ring, focus-visible:ring-ring/50)
--destructive: oklch(0.55 0.25 15) / oklch(0.704 0.191 22.216)   — invalid border + ring (aria-invalid:border-destructive, aria-invalid:ring-destructive/20)
--primary: oklch(0.5 0.14 155) / oklch(0.62 0.15 155)                         — text selection background (selection:bg-primary)
--primary-foreground: oklch(1 0 0) / oklch(0.1 0 0)              — text selection foreground (selection:text-primary-foreground)
--muted-foreground: oklch(0.52 0.06 155) / oklch(0.6 0.06 155)                — placeholder text (placeholder:text-muted-foreground)
 
## States
- focus-visible: border switches to --ring, 3px ring at ring/50 opacity
- aria-invalid:  border switches to --destructive, ring uses destructive/20 (light) or destructive/40 (dark)
- disabled:      opacity-50, cursor-not-allowed, interaction blocked
- dark bg:       dark:bg-input/30 — subtle tinted surface in dark mode
 
## Conventions
- Default minimum height is min-h-16 (64px) — override via className (e.g. className="min-h-32")
- Takes full width (w-full) by default; constrain via a wrapping element
- For dynamic height use the native rows attribute or react-textarea-autosize
- Pair with Label using htmlFor/id — Textarea has no built-in label
- Set aria-invalid to trigger the destructive ring on validation error
- Sub-components expose data-slot="textarea" for CSS targeting

Installation

GIN Design Plugin
$ npx shadcn add https://gin-design.vercel.app/textarea