Textarea
A multiline field for notes, descriptions, and longer text.
fieldform
Preview
Textarea preview
Live · keyboard ready
When to use
- Free-form multi-line text like bios, comments, or feedback.
- Fields with a live character count, which rolls its digits in the helper row.
When not to use
- Use input for single-line values.
- Use inline-edit with multiline for a description edited in place on a page.
- Use tag-input when the text is really a list of short values.
shadcn CLI
Also installs (1)
- manicat-foundation
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "textarea",
"type": "registry:ui",
"title": "Textarea",
"description": "A multiline field for notes, descriptions, and longer text.",
"categories": [
"inputs"
],
"dependencies": [
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json"
],
"files": [
{
"path": "registry/components/textarea/textarea.tsx",
"type": "registry:component",
"target": "@components/manicat/textarea/textarea.tsx"
},
{
"path": "registry/components/textarea/textarea.module.css",
"type": "registry:component",
"target": "@components/manicat/textarea/textarea.module.css"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/textarea",
"meta": {
"tier": "free",
"kind": "component",
"docs": "https://manicat.viraza.net/components/textarea",
"markdown": "https://uiarc.dev/components/textarea/markdown",
"tags": [
"field",
"form"
]
}
}Usage
Install the component, then copy this into your app. Change the content and the props to fit your screen.
example.tsxtsx
"use client";
import { useState } from "react";
import { Textarea } from "@/components/manicat/textarea/textarea";
export function TextareaExample() {
const [value, setValue] = useState("");
return (
<div className="grid w-full max-w-md gap-4">
<Textarea label="Changelog entry" placeholder="What changed?" value={value} onChange={(event) => setValue(event.target.value)} rows={5} />
<Textarea label="Short note" defaultValue="Kept to two lines." rows={2} description="Two lines is enough." />
</div>
);
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
Feedback form A message box with a live character counter that turns into an error past the limit.
Feedback form
A message box with a live character counter that turns into an error past the limit. preview
Live · keyboard ready
feedback-form-a-message-box-with-a-live-character-counter-that-turns-into-an-error-past-the-limit-.tsxtsx
"use client";
import { useState } from "react";
import { Button } from "@/components/manicat/button/button";
import { Textarea } from "@/components/manicat/textarea/textarea";
export function TextareaFeedbackExample() {
const [message, setMessage] = useState("");
const limit = 280;
const over = message.length > limit;
return (
<div className="grid w-full max-w-md gap-3">
<Textarea
label="What could be better?"
placeholder="Tell us what got in your way"
rows={4}
value={message}
onChange={(event) => setMessage(event.target.value)}
error={over ? `${message.length - limit} characters over the limit.` : undefined}
description={`${message.length}/${limit}`}
/>
<Button disabled={!message || over}>Send feedback</Button>
</div>
);
}
Accessibility
- Native textarea with a real label.
- Description and error ids are merged into aria-describedby; errors set aria-invalid and use role="alert".
- Animated copy is aria-hidden and mirrored in a visually hidden plain-text span.
Motion
- Message rows open their height on a smooth spring; changed words rise in with a soft blur and counts roll only the digits that changed.
- Reduced motion drops the roll, blur, and height spring for instant changes.
Responsive behavior
- It fills its column with a 110px minimum height and a vertical resize handle; it does not auto-grow with content.
- Hover border styles apply only on hover-capable fine pointers.
Performance
- One ResizeObserver per field measures the helper row for its height spring; cheap for a form, but avoid hundreds in a table.
- Recomputing a character count on each keystroke only re-renders the helper row words that changed.
Notes for AI
- Use for free-form, multi-line text. Use input for single lines and inline-edit for text edited in place on a page.
- A live character count in description gets the rolling-digit treatment for free.