TextArea

stable
Since 1.2
Multiline text field with label, description, error, optional character counting, and an explicit growth policy.
Forms
primitive
Form Control
Needs State Matrix
import { TextArea } from '@ivim/native/components';

When to use

Use when
Someone needs to write more than a line — notes, a message, a description.
You want to show how much room is left, using characterLimit.
Don't use when
The value is a single short string — use TextField.
The content needs formatting such as bold or lists — that is the text-editor family, which is not yet implemented.

Playground

Adjust the controls to preview live prop combinations. The code snippet updates to match the current selection.
Notes
0 / 280
Auto grow
autoGrow
Required
isRequired
Read only
isReadOnly
Disabled
isDisabled
Label
label
<TextArea label="Notes" />

Example

States
Default
Notes
With a character limit
Visit notes
49 / 280
Over the limit (reported, not truncated)
Summary
50 / 20
Auto-growing
Message
Required, with description
Notes
*
Include anything the care team should know.
With a tooltip
Visit notes
With an error
Notes
Read only
Notes
Disabled
Notes

Anatomy

The parts that compose this component.
1
Label
Field name; also the accessible name.
2
Field
The multiline control, fixed to rows or growing to maxRows.
3
Description or error
Helper text, replaced by the error when one appears.
4
Counter
Live "n / limit", announced politely so it does not interrupt typing.

Guidelines

Do
Size rows to the expected answer, so the field itself suggests how much to write.
Do
Show characterLimit when a limit exists, so it is visible before someone hits it rather than after.
Do
Use autoGrow with maxRows for composer-style fields where the content length varies widely.
Don't
Turn on enforceLimit without good reason — silently dropping pasted text feels broken.

Props

Public props for this component. Required props are marked; defaults reflect the component implementation.
value / defaultValue
string
Controlled and uncontrolled text.
onChangeText
(value: string) => void
Fires with the next value.
characterLimit
number
Shows a live counter. Advisory on its own — it never truncates.
enforceLimit
boolean
default: false
Rejects input past the limit. Off by default, because dropping pasted characters silently reads as a bug.
rows
number
default: 4
Visible rows when not auto-growing.
autoGrow / maxRows
boolean / number
default: false / 10
Grows with content up to maxRows, then scrolls.
label / description / errorMessage
ReactNode
Field anatomy; label and error reach the accessible name.
tooltip
string
Contextual help behind a small info affordance beside the label. Supplementary only — anything required to act belongs in description.
isInvalid
boolean
default: false
Marks the field invalid without supplying a message.

Deviations from Untitled UI

Where this component deliberately differs from Untitled UI's API, and why. These are kept choices, not gaps to close.
Untitled UI
`hint?: ReactNode` doubling as error text when invalid
Ours
`description` + `errorMessage`
UUI's `hint` is a UUI-ism layered over React Aria, which itself uses `description`/`errorMessage`. We follow the substrate; both slots can render simultaneously.

Accessibility

Roles and screen-reader behavior this component provides, plus keyboard interactions.
The label is forwarded as the accessible name, and the error is appended to it — React Native has no aria-labelledby or aria-describedby.
The character counter is announced politely (aria-live), so it does not interrupt typing.
Going over the limit marks the field invalid rather than truncating the value.
Read-only announces as an enabled control; disabled announces as unavailable.
Tab
Moves focus into and out of the field.
Enter
Inserts a line break rather than submitting.

Platform & RTL

Behavior that differs across the platforms this component runs on.
Web
Inset focus ring. There is deliberately no drag-to-resize handle — see the platform note below.
iOS
Grows via onContentSizeChange when autoGrow is set.
Android
Grows via onContentSizeChange when autoGrow is set.
RTL
Text direction follows the writing direction; the counter stays trailing.

State coverage

Interaction and visual states this component supports.
default
focus
error
disabled
selected

Token references

Semantic design tokens this component page exercises. Tap one to edit it live.