Skip to Content
ComponentsTextarea

Textarea

A multi-line text input with optional auto-resize behavior using the CSS field-sizing: content property.

Import

import { Textarea } from "chunks-ui";

Basic Usage

<Textarea placeholder="Write your message..." />

Auto-Resize

When autoResize is true, the textarea grows vertically to fit its content using the native CSS field-sizing: content property:

<Textarea autoResize placeholder="Start typing..." />

The textarea has a minimum height of min-h-ui-height by default.

With Field

Textarea is a field control, like Input. Inside Field.Root, Field.Label names it, Field.Description describes it, and disabled on the root disables it. When the field is invalid, the textarea gets aria-invalid and data-invalid, and the same red border as Input.

<Field.Root> <Field.Label>Bio</Field.Label> <Field.Description>Write a short bio (max 280 characters)</Field.Description> <Textarea autoResize placeholder="Tell us about yourself..." maxLength={280} /> </Field.Root>

Write a short bio (max 280 characters)

Controlled Value

Textarea passes value and defaultValue through Base UI, like Input. A controlled value must be controlled from the first render, so never start with undefined. Use value={bio ?? ""}. Switching between controlled and uncontrolled after mount leaves the textarea empty and logs a warning in development, and changing defaultValue after mount logs an error.

<Textarea value={bio ?? ""} onChange={(event) => setBio(event.target.value)} />

onValueChange gives you the new text directly, with the same signature as on Input: (value, eventDetails).

<Textarea value={bio ?? ""} onValueChange={setBio} />

Disabled

A disabled Textarea shows the not-allowed cursor and has no resize handle. Pass disabled:resize-y in className to keep the handle.

<Textarea disabled placeholder="This field is disabled" />

Text Size

The text is 16px below the md breakpoint (768px by default) and on a touch screen, so iOS Safari does not zoom the page when the field takes focus (it zooms into text under 16px); otherwise it is 14px, as in Input. With a mouse, a text-size class, such as text-lg, sets the size from md up. A max-md: class, such as max-md:text-lg, sets it below md, on a touch screen too; from md up on a touch screen, a md:[@media(pointer:coarse)]: class sets it. Where the text is 16px a row of text is 4px taller (24px), so a Textarea sized by its rows is taller there. See Text Size in Input for the limits.

Props

NameTypeDefault
autoResizeboolean

Enable auto-resize via CSS field-sizing: content.

false
onValueChange((value: string, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void) | undefined

Called with the new value and Base UI’s event details when the text changes, as on Input. Fires together with onChange.

All other props are forwarded to the underlying <textarea> element. className can also be a function of the field state (disabled, valid, touched, dirty, filled, focused).

Last updated on