@cf/textarea
Textarea
A multi-line text field that grows with its content, with focus and invalid states built in.
Describe what the image shows, not its file name.
Stock shadcn base-nova. field-sizing-content means it grows with what you type, with a min-h-16 floor and no ceiling, so give it a max-h-* wherever height matters. The chat composer uses max-h-40.
It styles aria-invalid itself (destructive border and ring), which Input doesn't yet. Nothing on the site uses Textarea on its own right now: the only multi-line field is the chat composer, which goes through InputGroupTextarea.
import { Textarea } from "@/components/ui/textarea";
<Textarea aria-label="Message" className="max-h-40" rows={1} />Rules
The same rules ship in DESIGN.md and the MCP server, for the agents building with this.
- must
Pair every Textarea with a
FieldLabelorLabelviahtmlForandid, or give it anaria-labelwhen there's no visible label.label-every-textarea
- must
Keep the
text-base md:text-smpairing if you override the text size; never go under 16px belowmd.iOS zooms into any field smaller than 16px and doesn't zoom back out.
keep-16px-on-touch
- should
Set a
max-h-*class when the textarea sits in a fixed layout, becausefield-sizing-contentlets it grow without limit.cap-the-growth
- must
Inside an
InputGroup, useInputGroupTextareainstead of Textarea.use-group-textarea-in-groups
Install
bunx shadcn@latest add @cf/textareaNeeds the @cf registry in your components.json once. The theme and any sibling components come along automatically.
Source
textarea.tsxShowHide
import { cn } from "cn";
import type * as React from "react";
function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
return (
<textarea
className={cn(
"field-sizing-content flex min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base outline-none transition-colors placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 dark:disabled:bg-input/80",
className
)}
data-slot="textarea"
{...props}
/>
);
}
export { Textarea };