Skip to main content

Textarea

Multi-line text input with label, helper text, validation, auto-resize and a character count.

1import { Textarea } from '@/components/ui/textarea';
2
3export function Default() {
4 return (
5 <div className="w-full max-w-sm">
6 <Textarea aria-label="Release notes" placeholder="What changed in this release?" />
7 </div>
8 );
9}

Installation

pnpm dlx nachui add textarea

Anatomy

1import { Textarea } from '@/components/ui/textarea';
1<Textarea label="Notes" description="Visible to the whole team." placeholder="Write something" />
The label, description, error and count are wired to the textarea through aria-describedby, so a screen reader announces them together. The id is generated when you do not pass one.

Variants

Default

1import { Textarea } from '@/components/ui/textarea';
2
3export function Default() {
4 return (
5 <div className="w-full max-w-sm">
6 <Textarea aria-label="Release notes" placeholder="What changed in this release?" />
7 </div>
8 );
9}

With label

label and description render above the field.
Shown on the public status page while the incident is open.
1import { Textarea } from '@/components/ui/textarea';
2
3export function WithLabel() {
4 return (
5 <div className="w-full max-w-sm">
6 <Textarea
7 label="Incident summary"
8 description="Shown on the public status page while the incident is open."
9 placeholder="Elevated error rates on the EU region"
10 rows={4}
11 />
12 </div>
13 );
14}

With error

error marks the field invalid and shows the message below it.

Request access

Tell the workspace owner why you need the production database.

Add at least 20 characters so the owner has context.
1import { Button } from '@/components/ui/button';
2import { Textarea } from '@/components/ui/textarea';
3
4export function WithError() {
5 return (
6 <div className="border-border bg-card flex w-full max-w-sm flex-col gap-4 rounded-xl border p-5">
7 <div>
8 <p className="text-sm font-medium">Request access</p>
9 <p className="text-muted-foreground text-xs">
10 Tell the workspace owner why you need the production database.
11 </p>
12 </div>
13 <Textarea
14 label="Reason"
15 defaultValue="debugging"
16 error="Add at least 20 characters so the owner has context."
17 rows={3}
18 />
19 <Button size="sm" className="self-start">
20 Send request
21 </Button>
22 </div>
23 );
24}

Auto resize

autoResize grows the textarea with its content. maxRows caps the height and the field scrolls past it.
Grows with what you type, up to six lines.
1import { Textarea } from '@/components/ui/textarea';
2
3export function AutoResize() {
4 return (
5 <div className="w-full max-w-sm">
6 <Textarea
7 label="Reply"
8 description="Grows with what you type, up to six lines."
9 placeholder="Thanks for the report, we are looking into it."
10 autoResize
11 maxRows={6}
12 />
13 </div>
14 );
15}

With count

showCount renders the current length. With maxLength it renders 12 / 160.
71 / 160
1import { Textarea } from '@/components/ui/textarea';
2
3export function WithCount() {
4 return (
5 <div className="w-full max-w-sm">
6 <Textarea
7 label="Short bio"
8 defaultValue="Platform engineer at Northwind Labs. I keep the deploy pipeline boring."
9 maxLength={160}
10 showCount
11 rows={3}
12 />
13 </div>
14 );
15}

Compound Components

The parts are exposed for custom layouts:
1<Textarea.Wrapper>
2 <Textarea.Label htmlFor="custom">Custom layout</Textarea.Label>
3 <Textarea.Description>Helper text goes here.</Textarea.Description>
4 <textarea id="custom" />
5 <Textarea.Error>Something went wrong.</Textarea.Error>
6</Textarea.Wrapper>

API Reference

Textarea

PropTypeDefaultDescription
labelstring-Label rendered above the textarea
descriptionstring-Helper text between the label and the field
errorstring-Error message, also sets aria-invalid
size"sm" | "default" | "lg""default"Padding and font size
resize"none" | "vertical" | "both""vertical"Which directions the user can drag
autoResizebooleanfalseGrow with the content and disable manual resize
maxRowsnumber-Maximum rows when autoResize is on
showCountbooleanfalseShow the character count
maxLengthnumber-Native limit, shown next to the count
classNamestring-Additional CSS classes
Every other attribute of a native textarea is passed through.

Textarea.Wrapper, Textarea.Label, Textarea.Description, Textarea.Error, Textarea.Count

Presentational parts. Each accepts className and the attributes of the element it renders.
Found something to improve?

Notice a bug, typo, or missing detail on this page? Help us make the documentation better by opening a GitHub issue.

Create an Issue
Ctrl+I