All Taste components
Forms
Textarea with count
A multi-line field that shows how many characters are used and turns amber near the limit.
default · near limit · optional label
Optional
Printed on the order ticket.80 / 200
Shown under your name in search.16 left
"use client";
import { useId, useState } from "react";
import { cn } from "@/lib/utils";
interface TextareaWithCountProps
extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, "defaultValue" | "maxLength"> {
label: string;
help?: string;
optional?: boolean;
max?: number;
defaultValue?: string;
}
export function TextareaWithCount({ label, help, optional, max = 200, defaultValue = "", className, ...props }: TextareaWithCountProps) {
const id = useId();
const [value, setValue] = useState(defaultValue);
const left = max - value.length;
const near = left <= 20;
return (
<div className="grid gap-1.5">
<div className="flex items-baseline justify-between gap-3">
<label htmlFor={id} className="text-[13px] font-medium text-fg">{label}</label>
{optional && <span className="text-xs text-fg-subtle">Optional</span>}
</div>
<textarea
id={id}
value={value}
maxLength={max}
aria-describedby={help ? id + "-help" : undefined}
onChange={(e) => setValue(e.target.value)}
className={cn(
"min-h-[84px] w-full resize-y rounded border border-border-strong bg-bg px-3 py-2 text-sm leading-relaxed text-fg outline-none transition",
"placeholder:text-fg-subtle focus:border-primary focus:ring-[3px] focus:ring-primary/20",
className,
)}
{...props}
/>
<div className="flex items-baseline justify-between gap-3">
{help && <p id={id + "-help"} className="text-xs text-fg-subtle">{help}</p>}
<p aria-hidden className={cn("ml-auto whitespace-nowrap text-xs tabular-nums", near ? "font-medium text-warning-fg" : "text-fg-subtle")}>
{near ? left + " left" : value.length + " / " + max}
</p>
{/* Screen readers hear the count only when it matters. */}
<span className="sr-only" aria-live="polite">{near ? left + " characters left" : ""}</span>
</div>
</div>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.