Field.Textarea

Field.Textarea is a native <textarea> for multi-line text inside a Field. Height is CSS only: rows sets the height and the drag floor, and maxRows sets the cap. Padding sits on the textarea, inside the shell. Pass onChange for the event or onValueChange for the new string, or both; without either, the textarea is read-only.

On this page
<Field.Root aria-label="Note">
  <Field.Textarea value={note} onChange={(event) => setNote(event.target.value)} rows={3} />
</Field.Root>

Height

autoGrow uses field-sizing: content where the browser has it, and grows with no cap when maxRows is omitted. Browsers without field-sizing stay at rows and scroll inside. Do not set an inline height when autoGrow is on; it overrides the growth.

autoGrow with maxRows={6}.

<Field.Root aria-label="Note">
  <Field.Textarea value={note} onChange={(event) => setNote(event.target.value)} autoGrow maxRows={6} />
</Field.Root>

maxRows without rows starts at min(3, maxRows).

Drag-resize with autoGrow off stops at rows and at maxRows.

Density and states

Compact, comfortable, and spacious.

Dark appearance, for the native scrollbar.

Label, description, error, invalid, and disabled.

A short description of the work.Use at least 8 characters.

Highlights

highlights draws ranges of the text as tokens, on a layer behind the textarea that copies its type, padding and scroll. Each range is { start, end }, with an optional kind set as data-kind, an anchorName a popover can sit at, and draw: false to keep only the anchor. useMentions sets it through getTextareaProps(), for mentions and slash commands. Tokens read field.token.bg and field.token.radius.

Accessible composition

Todae handles: The textarea takes id, name, aria-label, aria-labelledby and aria-describedby from Field.Root, and native disabled and aria-invalid from the Root or a surrounding Fieldset.

You supply: A name, through a Label whose htmlFor is the Root id or aria-label / aria-labelledby on the Root.

Watch for: An inline height with autoGrow on stops the growth. Without field-sizing, an autoGrow textarea stays at rows and scrolls.

When to use

Field.Textarea

When: Multi-line free text such as notes, messages or descriptions. rows sets the starting height, and autoGrow grows it up to maxRows with CSS only. When not: Single-line values, use Field.TextInput. Separate tags or tokens, use Field.ChipInput. Rich text or formatting, not shipped.

Props

Field.Textarea props
NameTypeDescription
value Requiredstring

Controlled value.

onChange(event: ChangeEvent<HTMLTextAreaElement>) => void

Native change handler. Optional when onValueChange is enough.

onValueChange(value: string) => void

Optional value callback.

placeholderstring

Native placeholder.

rowsnumber

Starting height in rows. Also the native rows attribute and the drag floor.

Default: "3"

maxRowsnumber

Caps autoGrow and drag-resize. Omitted means no cap.

autoGrowboolean

Grows with content up to maxRows using CSS only. No maxRows means no cap.

Default: "false"

highlightsreadonly FieldTextareaHighlight[]

Ranges of the text, { start, end, kind?, anchorName?, draw? }, drawn as tokens on a layer behind it. useMentions' getTextareaProps sets it.