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 · forms92 / 32,000
Embedded
Group draws the frame · composersNothing has been sent.
Rows and growth
Every row count Cloud uses. rows sets the starting height; the field then grows with its content.
States
Empty with a placeholder, filled, read-only, read-only while saving, disabled, and invalid.
Up to 1,000 characters.
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.
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.
No filter applied.
0/2000
No search built.
Form submission
A required textarea joins native form validation. It is disabled while the form saves.
Usage
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.