Textarea
Multi-line input for longer content with label, helper text, and error states.
01 Live Demo
0 characters
02 Code Snippet
src/ui/Textarea.tsx
import { Textarea } from "@/ui/Textarea"; <Textarea.Root label="Project notes" description="Write key updates for your team." placeholder="Type your notes here..." size="md" />
03 Copy-Paste (Single File)
Textarea.tsx
import { forwardRef, type TextareaHTMLAttributes } from "react"; type TextareaProps = TextareaHTMLAttributes<HTMLTextAreaElement> & { label?: string; description?: string; error?: string; }; const cn = (...classes: Array<string | undefined | false>) => classes.filter(Boolean).join(" "); const TextareaRoot = forwardRef<HTMLTextAreaElement, TextareaProps>(function TextareaRoot( { label, description, error, className, ...props }, ref ) { return ( <div className={cn("flex flex-col gap-1.5", className)}> {label && <label className="text-sm font-medium text-slate-700 dark:text-slate-300">{label}</label>} <textarea ref={ref} className={cn( "min-h-24 w-full rounded-lg border border-slate-200 bg-white px-3.5 py-2.5 text-sm text-slate-900 outline-hidden", "focus:border-primary focus:ring-2 focus:ring-primary/20 dark:border-[#1f2937] dark:bg-[#0d1117] dark:text-white", error && "border-red-400 focus:border-red-400 focus:ring-red-400/20" )} {...props} /> {description && !error && <p className="text-xs text-slate-500 dark:text-slate-400">{description}</p>} {error && <p className="text-xs text-red-500 dark:text-red-400">{error}</p>} </div> ); }); type TextareaCompound = typeof TextareaRoot & { Root: typeof TextareaRoot }; export const Textarea = Object.assign(TextareaRoot, { Root: TextareaRoot }) as TextareaCompound;