Inputs
Textarea
A multi-line text field for notes, descriptions and messages. It can grow with its content up to a maximum number of rows, and show a live character counter that warns as the limit gets close.
98 of 280 characters used
Ada sees this on the shared invoice.
<div className="mx-auto w-full max-w-md rounded-ui-lg border border-line bg-surface p-4 shadow-ui"> <Field label="Reply to Ada Moreno" hint="Ada sees this on the shared invoice."> <Textarea autoGrow maxRows={8} showCount maxLength={280} placeholder="Write a reply…" defaultValue="Thanks Ada, the revised quote for the Fernhill rebrand is attached. Payment terms stay at 14 days." /> </Field> <div className="mt-3 flex items-center justify-between gap-2"> <Button variant="ghost" size="icon-sm" aria-label="Attach file"> <Paperclip strokeWidth={1.75} /> </Button> <Button variant="primary" size="sm">Send reply</Button> </div></div>Usage
components/ui/textarea.tsx
import { Field } from "@/components/ui/field";import { Textarea } from "@/components/ui/textarea"; export function Example() { return ( <Field label="Notes"> <Textarea autoGrow showCount maxLength={500} /> </Field> );}Examples
Message composer
98 of 280 characters used
Ada sees this on the shared invoice.
<div className="mx-auto w-full max-w-md rounded-ui-lg border border-line bg-surface p-4 shadow-ui"> <Field label="Reply to Ada Moreno" hint="Ada sees this on the shared invoice."> <Textarea autoGrow maxRows={8} showCount maxLength={280} placeholder="Write a reply…" defaultValue="Thanks Ada, the revised quote for the Fernhill rebrand is attached. Payment terms stay at 14 days." /> </Field> <div className="mt-3 flex items-center justify-between gap-2"> <Button variant="ghost" size="icon-sm" aria-label="Attach file"> <Paperclip strokeWidth={1.75} /> </Button> <Button variant="primary" size="sm">Send reply</Button> </div></div>Auto-grow
autoGrow resizes the field to fit what's typed, from rows up to maxRows, then scrolls. Type a few lines to try it.
<div className="mx-auto w-full max-w-sm"> <Field label="Project brief"> <Textarea autoGrow rows={2} maxRows={6} placeholder="What should the team know before kick-off?" /> </Field></div>Character counter
showCount displays the count; with maxLength it reads 42/160 and turns amber at 90% and red at the limit.
85 of 160 characters used
65 of 70 characters used
<div className="mx-auto flex w-full max-w-sm flex-col gap-5"> <Field label="Meta description"> <Textarea showCount maxLength={160} defaultValue="Plinth is a themeable component library for teams that ship polished product UI fast." /> </Field> <Field label="SMS reminder"> <Textarea showCount maxLength={70} rows={2} defaultValue="Hi Ada, invoice FHS-0142 is due tomorrow. Pay at ledgerly.example" /> </Field></div>States
Tell us why so we can refund the right amount.
Locked after the invoice is sent.
<div className="mx-auto grid w-full max-w-xl gap-5 sm:grid-cols-2"> <Field label="Cancellation reason" error="Tell us why so we can refund the right amount."> <Textarea rows={3} /> </Field> <Field label="Internal note" hint="Locked after the invoice is sent." disabled> <Textarea rows={3} defaultValue="Approved by Rui on 12 Oct." /> </Field></div>Props
PropTypeDefaultDescription
autoGrowbooleandefault: falseGrow with the content instead of scrolling.rowsnumberdefault: 3Starting height in rows.maxRowsnumberdefault: 10Height limit for autoGrow; scrolls beyond it.showCountbooleandefault: falseLive character counter under the text. Uses maxLength as the limit.maxLengthnumberdefault: —Native limit; the counter warns at 90%.invalidbooleandefault: —Red border and aria-invalid. Set automatically by <Field error>.classNamestringdefault: —Classes for the outer box.textareaClassNamestringdefault: —Classes for the inner <textarea>....propsTextareaHTMLAttributesdefault: —Any native textarea attribute: value, onChange, placeholder…
Accessibility
- A native <textarea>, so all text editing keys, spell check and IME input work as expected.
- Inside Field the label, hint and error are linked automatically (label for, aria-describedby, aria-invalid).
- The counter is part of aria-describedby and reads as “42 of 160 characters used”, not just numbers.
- maxLength is enforced by the browser; the amber and red counter colors are backed by the number itself, never color alone.