Github

Textarea

Displays a form textarea or a component that looks like a textarea.

import { Textarea } from "@/components/ui/textarea";

export function TextareaDemo() {
	return (
		<div className="w-full max-w-sm">
			<Textarea placeholder="Type your message here." rows={4} />
		</div>
	);
}

Installation

pnpm dlx shadcn@latest add https://herocn.dev/r/textarea.json

Usage

import { Textarea } from "@/components/ui/textarea"
<Textarea placeholder="Type your message here." />

Examples

Variants

Use the variant prop for a softer background on the secondary style.

import { Textarea } from "@/components/ui/textarea";

export function TextareaVariants() {
	return (
		<div className="flex w-full max-w-sm flex-col gap-3">
			<Textarea placeholder="Default" rows={3} />
			<Textarea variant="secondary" placeholder="Secondary" rows={3} />
		</div>
	);
}

States

Disabled textareas are non-interactive. Set aria-invalid for error styling (for example when validation fails).

import { Textarea } from "@/components/ui/textarea";

export function TextareaStates() {
	return (
		<div className="flex w-full max-w-sm flex-col gap-3">
			<Textarea disabled placeholder="Disabled" rows={3} />
			<Textarea
				aria-invalid
				placeholder="Invalid"
				defaultValue="Invalid value"
				rows={3}
			/>
		</div>
	);
}

With field

Pair Textarea with Field, FieldLabel, and FieldDescription for accessible labels and helper text.

We read every submission and aim to reply within two business days.

import {
	Field,
	FieldDescription,
	FieldLabel,
} from "@/components/ui/field";
import { Textarea } from "@/components/ui/textarea";

export function TextareaField() {
	return (
		<div className="w-full max-w-sm">
			<Field>
				<FieldLabel htmlFor="textarea-field-message">Message</FieldLabel>
				<Textarea
					id="textarea-field-message"
					placeholder="Type your message here."
					rows={4}
				/>
				<FieldDescription>
					We read every submission and aim to reply within two business days.
				</FieldDescription>
			</Field>
		</div>
	);
}

With button

Stack a submit action below the control for quick feedback or messaging forms.

import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";

export function TextareaButton() {
	return (
		<div className="grid w-full max-w-sm gap-2">
			<Textarea placeholder="Type your message here." rows={4} />
			<Button className="w-full">Send message</Button>
		</div>
	);
}

In surface

Use variant="secondary" when placing a Textarea inside a card or panel surface for a subtler, shadow-free appearance that blends with the surface background.

Leave a comment

Your feedback helps us improve the product.

import { Button } from "@/components/ui/button";
import {
	Card,
	CardContent,
	CardFooter,
	CardHeader,
	CardTitle,
} from "@/components/ui/card";
import {
	Field,
	FieldDescription,
	FieldLabel,
} from "@/components/ui/field";
import { Textarea } from "@/components/ui/textarea";

export function TextareaInSurface() {
	return (
		<Card className="w-full max-w-sm">
			<CardHeader>
				<CardTitle>Leave a comment</CardTitle>
			</CardHeader>
			<CardContent>
				<Field>
					<FieldLabel htmlFor="textarea-in-surface-message">Message</FieldLabel>
					<Textarea
						id="textarea-in-surface-message"
						variant="secondary"
						placeholder="Share your thoughts..."
						rows={4}
					/>
					<FieldDescription>
						Your feedback helps us improve the product.
					</FieldDescription>
				</Field>
			</CardContent>
			<CardFooter className="justify-end gap-2">
				<Button variant="ghost" size="sm">
					Cancel
				</Button>
				<Button size="sm">Submit</Button>
			</CardFooter>
		</Card>
	);
}

RTL

شاركنا أفكارك حول خدمتنا.

"use client";

import {
	type Translations,
	useTranslation,
} from "@/components/language-selector";
import {
	Field,
	FieldDescription,
	FieldLabel,
} from "@/components/ui/field";
import { Textarea } from "@/components/ui/textarea";

const translations: Translations = {
	en: {
		dir: "ltr",
		values: {
			label: "Feedback",
			placeholder: "Your feedback helps us improve...",
			description: "Share your thoughts about our service.",
		},
	},
	ar: {
		dir: "rtl",
		values: {
			label: "التعليقات",
			placeholder: "تعليقاتك تساعدنا على التحسين...",
			description: "شاركنا أفكارك حول خدمتنا.",
		},
	},
	he: {
		dir: "rtl",
		values: {
			label: "משוב",
			placeholder: "המשוב שלך עוזר לנו להשתפר...",
			description: "שתף את מחשבותיך על השירות שלנו.",
		},
	},
};

export function TextareaRtl() {
	const { dir, language, t } = useTranslation(translations, "ar");

	return (
		<div className="w-full max-w-sm" lang={language} dir={dir}>
			<Field>
				<FieldLabel htmlFor="textarea-rtl-feedback">{t.label}</FieldLabel>
				<Textarea
					id="textarea-rtl-feedback"
					placeholder={t.placeholder}
					rows={4}
				/>
				<FieldDescription>{t.description}</FieldDescription>
			</Field>
		</div>
	);
}

API Reference

Textarea

The Textarea component accepts all props from a native <textarea> plus the following:

PropTypeDefault