Textarea

A multi-line text field. Use it for agent instructions, task prompts, notes, replies, and pasted text. It grows with its content.

Variants

default is the bordered form control. embedded drops its frame so a composer group draws the border and focus ring.

Default

Own border and ring · forms

92 / 32,000

Describe its role, tone, responsibilities, and when it should ask a person.

Embedded

Group draws the frame · composers
Draft message

Nothing has been sent.

Rows and growth

Every row count Cloud uses. rows sets the starting height; the field then grows with its content.

No rows · 96px floor
Optional
rows={3} · 96px floor
Optional
rows={5} · 118px
Optional
rows={9} · 198px
Optional
rows={10} · 218px
Optional
rows={12} · 258px
Optional

States

Empty with a placeholder, filled, read-only, read-only while saving, disabled, and invalid.

Optional

Only stored in this example.

Up to 1,000 characters.

Optional

Connect Gmail to edit these.

Enter a request.

Labels and descriptions

A Sprõut Field, a label with htmlFor and aria-describedby, a label that wraps the textarea, and a disabled fieldset.

Plain text. Jira converts line breaks.

Enter a summary.

Run manually

Ask a manager for run permission to start runs.

Keyboard submit and loading

⌘ Enter or Ctrl Enter submits; Enter adds a line. The RSQL field inherits a monospace font. Building a search disables the field.

Optional

A field name, an operator, and a value. Applied filters appear as chips.

⌘Enter

No filter applied.

Optional

0/2000

For example: open urgent tickets from last week, newest first.

No search built.

Form submission

A required textarea joins native form validation. It is disabled while the form saves.

Usage

Textarea usageTSX
import { Field } from "@tulipfarm/sprout/field";
import { Textarea } from "@tulipfarm/sprout/textarea";

const [prompt, setPrompt] = useState("");

<Field
  label="Task prompt"
  required
  counter={`${prompt.length.toLocaleString()} / 8,000`}
  error={prompt.trim() ? undefined : "Enter a prompt."}
>
  <Textarea
    rows={3}
    maxLength={8000}
    value={prompt}
    placeholder="Prepare the weekly People Ops update."
    onChange={(event) => setPrompt(event.target.value)}
  />
</Field>

<Label htmlFor="provider-instructions">Instructions</Label>
<Textarea id="provider-instructions" value={instructions} readOnly rows={5} />

Textarea renders a native textarea and takes every textarea prop:value or defaultValue,onChange, ref, rows,maxLength, required, readOnly,spellCheck, and event handlers such asonKeyDown.

Props

variant is "default" (1px border, surface fill, 2px focus ring) or "embedded" (no border, fill, ring, or resize handle). Use embedded inside a group that draws the frame, such as a message composer. The group can draw its ring with :has(.sprout-textarea:focus-visible).

Both variants use 14px text on 20px lines with 8px by 10px padding. The field starts at 96px, or at rows lines when that is taller, and grows with its content where the browser supportsfield-sizing: content. Elsewhere it keeps that height and scrolls. A default textarea can be resized vertically.

disabled dims the textarea and blocks edits.readOnly keeps it focusable and selectable, which suits setup instructions and saving states. aria-invalid draws a danger border and focus ring. The textarea inherits its font family, so a monospace wrapper suits query editors. It setsdata-slot="textarea" and data-variant.

With a field

Inside a Sprõut Field, Textarea reads the field throughuseFieldControl. The field gives it an id, a label, the helper, error, requirement, and counter descriptions, and itsdisabled, aria-invalid, andaria-required states. Without a field, pairid with a Label htmlFor, wrap it in aLabel, or use aria-label.

Accessibility

Every textarea needs a name. Point aria-describedby at help and error text. Enter adds a line; when ⌘ Enter or Ctrl Enter submits, say so near the field. Read-only textareas stay in the tab order; disabled ones, and ones in a disabled fieldset, leave it.

Color changes take 120ms and stop when reduced motion is requested. In forced colors mode the textarea keeps a system border and a highlight focus ring.

Theme tokens

The border uses --sprout-input, the fill--sprout-surface, text --sprout-text, and the placeholder --sprout-muted. Focus uses--sprout-focus, invalid --sprout-danger, and disabled --sprout-hover. Radius follows--sprout-radius-control. The opt-in TulipFarm theme tints the focus ring through these tokens.