Textarea

A polished multi-line form primitive for product interfaces. It handles labels, helper text, error messaging, character counts, auto-resize, disabled and read-only states, and default, filled, and ghost visual variants from one installable component.

Loading preview...

Examples

Practical examples and common states for the same installable component.

Message

Standard textarea for support forms and contact flows.

examples/textarea-message.tsx
import { Textarea } from "@/components/wensity/textarea";
export function TextareaMessage() {
return (
<Textarea
label="Message"
placeholder="Describe what happened..."
hint="Include the page, action, and expected result."
/>
);
}

Filled

Soft filled surface for dense product panels and notes.

examples/textarea-filled.tsx
import { Textarea } from "@/components/wensity/textarea";
export function TextareaFilled() {
return (
<Textarea
variant="filled"
label="Internal note"
defaultValue="The customer asked for workspace-level permissions before inviting the rest of the team."
hint="Only visible to admins."
minRows={4}
/>
);
}

Ghost

Quiet editor field for composer surfaces.

examples/textarea-ghost.tsx
"use client";
import * as React from "react";
import { Textarea } from "@/components/wensity/textarea";
export function TextareaGhost() {
const [value, setValue] = React.useState(
"Turn this release summary into a short changelog for the customer portal.",
);
return (
<Textarea
aria-label="AI prompt"
variant="ghost"
value={value}
onChange={(event) => setValue(event.target.value)}
showCount
maxLength={180}
minRows={4}
resize="none"
/>
);
}

Error

Validation updates border, focus ring, and aria-invalid.

examples/textarea-error.tsx
import { Textarea } from "@/components/wensity/textarea";
export function TextareaError() {
return (
<Textarea
label="Reproduction steps"
defaultValue="It broke."
error="Add at least two clear steps so the team can reproduce it."
minRows={4}
/>
);
}

Auto Resize

Grow with content until the configured maximum row count.

examples/textarea-auto-resize.tsx
"use client";
import * as React from "react";
import { Textarea } from "@/components/wensity/textarea";
export function TextareaAutoResize() {
const [value, setValue] = React.useState(
"Auto-resize keeps short notes compact, then grows until the configured maximum row count.",
);
return (
<Textarea
label="Brief"
value={value}
onChange={(event) => setValue(event.target.value)}
autoResize
minRows={3}
maxRows={8}
hint="Try adding more lines; the field grows without layout jumps."
/>
);
}

Character Count

Count text is connected to aria-describedby automatically.

examples/textarea-character-count.tsx
"use client";
import * as React from "react";
import { Textarea } from "@/components/wensity/textarea";
export function TextareaCharacterCount() {
const [value, setValue] = React.useState(
"A compact component library for shipping premium app interfaces faster.",
);
return (
<Textarea
label="Short bio"
value={value}
onChange={(event) => setValue(event.target.value)}
maxLength={110}
showCount
minRows={3}
resize="none"
hint="Keep it direct and useful."
/>
);
}

Sizes

Small, default, and large sizes for different content density.

examples/textarea-sizes.tsx
import { Textarea } from "@/components/wensity/textarea";
export function TextareaSizes() {
return (
<div className="flex items-end gap-3">
<Textarea textareaSize="sm" label="Small" placeholder="Triage note" />
<Textarea textareaSize="md" label="Default" placeholder="Team update" />
<Textarea textareaSize="lg" label="Large" placeholder="Launch plan" />
</div>
);
}

Read-only

Read-only values stay selectable while reducing emphasis.

examples/textarea-readonly.tsx
import { Textarea } from "@/components/wensity/textarea";
export function TextareaReadonly() {
return (
<Textarea
label="Generated summary"
value="The workspace billing role changed from Member to Admin on June 16, 2026."
readOnly
minRows={3}
resize="none"
/>
);
}

Disabled

Disabled textareas block interaction while keeping layout stable.

examples/textarea-disabled.tsx
import { Textarea } from "@/components/wensity/textarea";
export function TextareaDisabled() {
return (
<Textarea
label="Cancellation reason"
defaultValue="Workspace was archived by an organization owner."
disabled
minRows={3}
resize="none"
/>
);
}