Textarea

Multi-line input, with character count, with toolbar.
Pass label (and required) to name the field: iOS and web render the label above the control, while Android floats the Material 3 in-container label at the top of the multiline box, making room for itself at the user's text size and truncating on one line when it is longer than the box while the field's accessible name stays the whole label. The required star is decorative: a screen reader hears the field as required, from aria-required on the web and from its name ("Bio, required") on iOS and Android. The box fills the parent it is given; a step of its own (xs, lg, …, with start to pin it to the leading edge) or a Container step sets its measure.
Android uses the same opaque muted surface as the other filled fields. Its label uses primary-text when focused and destructive-text on error. The over-limit character count also uses destructive-text on every platform.
Inside an overlay, Escape follows the overlay's cancellation policy. A supplied onKeyPress runs first and can call preventDefault() to handle Escape locally. Cancelling an IME candidate keeps the overlay open.
iOS
Android
Web
tsx
<Textarea placeholder="A few words about this project" />

Props

Prop
Description
value
string
Controlled text value. Omit and use `defaultValue` for uncontrolled use.
onChangeText
(next: string) => void
Fired with the next text value on each edit.
placeholder
string
Placeholder shown while the field is empty.
label
string
The field's persistent label. Its placement is platform-adaptive: iOS and web render it ABOVE the field; Android renders the Material 3 in-container FLOATING label — a MULTILINE float pinned to the first text line at rest, floating to the top once the field is focused or filled. The label names the field for a11y.
required
boolean
Marks the field as required: appends a destructive "*" to the label (decorative, never in the accessible name) and announces the field as required, through aria-required on the web and with the word in its name ("Bio, required") on iOS and Android. The star and the spoken word take effect only alongside `label`.
rows
number
Visible rows the field sizes to. Sets the min height (rows * ~22px + 16px padding); the field still grows with content past this floor.
showCount
boolean
Show a live character-count line inside the field's own anatomy: an end-aligned muted caption under the control reading "N / max" (just "N" when no `maxLength` is set), where N is the current text length. When on, `maxLength` becomes a SOFT cap rather than a hard one: it is NOT forwarded to the native TextInput (a hard cap silently drops the extra keystroke, so the overage could never be seen), the user can type past it, and once N exceeds `maxLength` the count turns destructive AND the field enters its error state automatically (red border/underline). Leave `showCount` off to keep `maxLength` as a hard input cap.
error
boolean
Error/validation state: a destructive cue. `invalid` is an alias.
invalid
boolean
—
small
boolean
Size (pick one; default is the base text-sm field).
large
boolean
Size (pick one; default is the base text-sm field).
disabled
boolean
Blocks editing and focus, and dims the field.
flush
boolean
Borderless: drop the field's own border and radius so it sits flush inside a framed container (e.g. a Card with a formatting toolbar above it).
style
StyleProp<Omit<TextStyle, SizingKey>>
Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.
textContentType
'none' | 'URL' | 'addressCity' | 'addressCityAndState' | 'addressState' | 'countryName' | 'creditCardNumber' | 'creditCardExpiration' | 'creditCardExpirationMo…
Give the keyboard and the system information about the expected semantic meaning for the content that users enter. To disable autofill, set textContentType to `none`. Possible values for `textContentType` are: - `'none'` - `'URL'` - `'addressCity'` - `'addressCityAndState'` - `'addressState'` - `'countryName'` - `'creditCardNumber'` - `'creditCardExpiration'` (iOS 17+) - `'creditCardExpirationMonth'` (iOS 17+) - `'creditCardExpirationYear'` (iOS 17+) - `'creditCardSecurityCode'` (iOS 17+) - `'creditCardType'` (iOS 17+) - `'creditCardName'` (iOS 17+) - `'creditCardGivenName'` (iOS 17+) - `'creditCardMiddleName'` (iOS 17+) - `'creditCardFamilyName'` (iOS 17+) - `'emailAddress'` - `'familyName'` - `'fullStreetAddress'` - `'givenName'` - `'jobTitle'` - `'location'` - `'middleName'` - `'name'` - `'namePrefix'` - `'nameSuffix'` - `'nickname'` - `'organizationName'` - `'postalCode'` - `'streetAddressLine1'` - `'streetAddressLine2'` - `'sublocality'` - `'telephoneNumber'` - `'username'` - `'password'` - `'newPassword'` - `'oneTimeCode'` - `'birthdate'` (iOS 17+) - `'birthdateDay'` (iOS 17+) - `'birthdateMonth'` (iOS 17+) - `'birthdateYear'` (iOS 17+) - `'cellularEID'` (iOS 17.4+) - `'cellularIMEI'` (iOS 17.4+) - `'dateTime'` (iOS 15+) - `'flightNumber'` (iOS 15+) - `'shipmentTrackingNumber'` (iOS 15+)
xxxs
boolean
Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.
xxs
boolean
Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.
xs
boolean
Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.
sm
boolean
Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.
md
boolean
Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.
lg
boolean
Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.
xl
boolean
Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.
xxl
boolean
Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.
xxxl
boolean
Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.
wide
boolean
Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.
wider
boolean
Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.
widest
boolean
Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.
page
boolean
Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.
start
boolean
Pin a capped component to the leading edge instead of centering it in its column.
autoCapitalize
'none' | 'sentences' | 'words' | 'characters'
Can tell TextInput to automatically capitalize certain characters. characters: all characters, words: first letter of each word sentences: first letter of each sentence (default) none: don't auto capitalize anything https://reactnative.dev/docs/textinput#autocapitalize
autoComplete
'2fa-app-otp' | 'additional-name' | 'address-line1' | 'address-line2' | 'birthdate-day' | 'birthdate-full' | 'birthdate-month' | 'birthdate-year' | 'cc-csc' | …
Specifies autocomplete hints for the system, so it can provide autofill. On Android, the system will always attempt to offer autofill by using heuristics to identify the type of content. To disable autocomplete, set autoComplete to off. The following values work across platforms: - `additional-name` - `address-line1` - `address-line2` - `cc-number` - `country` - `current-password` - `email` - `family-name` - `given-name` - `honorific-prefix` - `honorific-suffix` - `name` - `new-password` - `off` - `one-time-code` - `postal-code` - `street-address` - `tel` - `username` The following values work on iOS only: - `nickname` - `organization` - `organization-title` - `url` The following values work on Android only: - `birthdate-day` - `birthdate-full` - `birthdate-month` - `birthdate-year` - `cc-csc` - `cc-exp` - `cc-exp-day` - `cc-exp-month` - `cc-exp-year` - `2fa-app-otp` - `email-otp` - `flight-confirmation-code` - `flight-number` - `gender` - `gift-card-number` - `gift-card-pin` - `loyalty-account-number` - `name-family` - `name-given` - `name-middle` - `name-middle-initial` - `name-prefix` - `name-suffix` - `password` - `password-new` - `postal-address` - `postal-address-country` - `postal-address-dependent-locality` - `postal-address-extended` - `postal-address-extended-postal-code` - `postal-address-locality` - `postal-address-region` - `postal-address-unit` - `promo-code` - `sms-otp` - `tel-country-code` - `tel-national` - `tel-device` - `upi-vpa` - `wifi-password` - `username-new`
autoCorrect
boolean
If false, disables auto-correct. The default value is true.
autoFocus
boolean
If true, focuses the input on componentDidMount. The default value is false.
defaultValue
string
Provides an initial value that will change when the user starts typing. Useful for simple use-cases where you don't want to deal with listening to events and updating the value prop to keep the controlled state in sync.
keyboardType
KeyboardTypeOptions
enum("default", 'numeric', 'email-address', "ascii-capable", 'numbers-and-punctuation', 'url', 'number-pad', 'phone-pad', 'name-phone-pad', 'decimal-pad', 'twitter', 'web-search', 'visible-password') Determines which keyboard to open, e.g.numeric. The following values work across platforms: - default - numeric - email-address - phone-pad The following values work on iOS: - ascii-capable - numbers-and-punctuation - url - number-pad - name-phone-pad - decimal-pad - twitter - web-search The following values work on Android: - visible-password
inputMode
InputModeOptions
Works like the inputmode attribute in HTML, it determines which keyboard to open, e.g. numeric and has precedence over keyboardType.
maxLength
number
Limits the maximum number of characters that can be entered. Use this instead of implementing the logic in JS to avoid flicker.
onBlur
((e: BlurEvent) => void)
Callback that is called when the text input is blurred Note: If you are trying to find the last value of TextInput, you can use the `onEndEditing` event, which is fired upon completion of editing.
onFocus
((e: FocusEvent) => void)
Callback that is called when the text input is focused
onSubmitEditing
((e: TextInputSubmitEditingEvent) => void)
Callback that is called when the text input's submit button is pressed.
onKeyPress
((e: TextInputKeyPressEvent) => void)
Callback that is called when a key is pressed. This will be called with `{ nativeEvent: { key: keyValue } }` where keyValue is 'Enter' or 'Backspace' for respective keys and the typed-in character otherwise including ' ' for space. Fires before onChange callbacks. Note: on Android only the inputs from soft keyboard are handled, not the hardware keyboard inputs.
returnKeyType
ReturnKeyTypeOptions
enum('default', 'go', 'google', 'join', 'next', 'route', 'search', 'send', 'yahoo', 'done', 'emergency-call') Determines how the return key should look.
secureTextEntry
boolean
If true, the text input obscures the text entered so that sensitive text like passwords stay secure. The default value is false.
testID
string
Used to locate this view in end-to-end tests
ref
React.Ref<RNTextInput>
Ref to the underlying React Native host. Supports object refs and callback refs; native methods follow the platform's behavior.

Do & Don’t

With label

Don’t
Description
A locked, single-line textarea hides long content with no way to expand.
Do
Description
Set rows for a sensible starting height so users can see their text; the field grows with the content from there.

Character counter

Don’t
Bio
over limit
A vague "over limit" message gives no number, so users cannot tell how much to trim.
Do
Bio
129 / 120
Show the live count against the cap and turn it destructive past the limit so the overage is precise. showCount treats maxLength as a soft cap and flips the count (and the field) destructive automatically once you run over.

Formatting toolbar

Don’t
B
I
</>
Static, unclickable glyphs look like a toolbar but cannot be pressed or focused.
Do
Make each control a real focusable button that toggles an active state when pressed.

Disabled

Don’t
Description
Dimming a textarea while leaving it editable looks disabled but still accepts input.
Do
Description
Pass disabled so the field blocks editing and focus, matching its dimmed look: the browser takes it out of the tab order, and VoiceOver and TalkBack announce it as dimmed.