TextArea
Multiline input that can grow with its content.
Installation
npx axiom add text-areapnpm dlx axiom add text-areayarn dlx axiom add text-areabun x axiom add text-areaAlso copies input: TextArea uses its tokens, its Field parts and use-input.ts.
Usage
import { Field } from "@/components/ui/input";
import { TextArea } from "@/components/ui/text-area";
<Field>
<Field.Label>Message</Field.Label>
<TextArea autoGrow value={message} onChangeText={setMessage} />
</Field>;Like Input, TextArea is the control alone. The label, description, error and a character count are things you write around it, in a Field.
Props
TextArea accepts the same props as Input (invalid, disabled, containerStyle, ref, and every TextInput prop) except prefix, suffix and size, plus:
| Prop | Type | Default | Description |
|---|---|---|---|
autoGrow | boolean | false | The field gets taller as lines are added, between minRows and maxRows. Past maxRows it scrolls. |
minRows | number | 3 | Height when empty, in lines of body text. Lines get taller with larger system text, up to 1.5×. |
maxRows | number | 8 | Height limit with autoGrow. Keeps the field from pushing the rest of the screen off. |
maxLength | number | — | Hard character limit, from TextInput. |
variant | 'outline' | 'filled' | 'plain' | 'outline' | plain has no border or padding, for full-screen editors. It grows to fill its container. |
Use cases
Chat composer
autoGrow with a low maxRows: one line at rest, a few lines while typing, then scroll.
<TextArea
autoGrow
minRows={1}
maxRows={5}
placeholder="Message"
value={draft}
onChangeText={setDraft}
/>Feedback with a character limit
A count next to the description tells the user how much room is left. It’s a Text you write, so its place and its wording are yours.
<Field>
<Field.Label>What happened?</Field.Label>
<TextArea maxLength={200} value={text} onChangeText={setText} />
<View style={{ flexDirection: "row", gap: 12 }}>
<Field.Description style={{ flex: 1 }}>
Steps help us reproduce it.
</Field.Description>
<Text variant="footnote" color={text.length >= 200 ? "error" : "muted"}>
{text.length} / 200
</Text>
</View>
</Field>Full-screen note
variant="plain" removes the field chrome: the screen itself is the editor.
<TextArea
variant="plain"
autoFocus
value={body}
onChangeText={setBody}
accessibilityLabel="Note"
containerStyle={{ flex: 1 }}
/>