Reference version

TextField

Jetpack Compose TextField components for native Material3 text input.

Android
Bundled version:
~55.0.10

Expo UI provides two text field components that match the official Jetpack Compose TextField API: TextField (filled) and OutlinedTextField (outlined border). Both variants share the same props and support composable slot children for label, placeholder, icons, prefix, suffix, and supporting text.

TypeAppearancePurpose
FilledSolid background with a bottom indicator line.Default text input style following Material3 design. Use for most forms and input fields.
OutlinedTransparent background with a border outline.Alternative style that provides a distinct visual boundary. Use when filled fields blend into the background.

Installation

Terminal
- npx expo install @expo/ui

If you are installing this in an existing React Native app, make sure to install expo in your project.

Usage

Basic text field

A filled text field is the default Material3 text input style.

BasicTextFieldExample.tsx
import { useState } from 'react'; import { Host, TextField, Text } from '@expo/ui/jetpack-compose'; export default function BasicTextFieldExample() { const [value, setValue] = useState(''); return ( <Host matchContents> <TextField onValueChange={setValue}> <TextField.Label> <Text>Username</Text> </TextField.Label> </TextField> </Host> ); }

Outlined text field

Use OutlinedTextField for a text field with a border outline instead of a filled background.

OutlinedTextFieldExample.tsx
import { useState } from 'react'; import { Host, OutlinedTextField, Text } from '@expo/ui/jetpack-compose'; export default function OutlinedTextFieldExample() { const [value, setValue] = useState(''); return ( <Host matchContents> <OutlinedTextField onValueChange={setValue}> <OutlinedTextField.Label> <Text>Email</Text> </OutlinedTextField.Label> <OutlinedTextField.Placeholder> <Text>you@example.com</Text> </OutlinedTextField.Placeholder> </OutlinedTextField> </Host> ); }

Slots

Both TextField and OutlinedTextField support 7 composable slots that match the Compose API: Label, Placeholder, LeadingIcon, TrailingIcon, Prefix, Suffix, and SupportingText.

TextFieldSlotsExample.tsx
import { useState } from 'react'; import { Host, TextField, Text } from '@expo/ui/jetpack-compose'; export default function TextFieldSlotsExample() { const [value, setValue] = useState(''); return ( <Host matchContents> <TextField onValueChange={setValue}> <TextField.Label> <Text>Price</Text> </TextField.Label> <TextField.Placeholder> <Text>0.00</Text> </TextField.Placeholder> <TextField.LeadingIcon> <Text>💰</Text> </TextField.LeadingIcon> <TextField.Prefix> <Text>$</Text> </TextField.Prefix> <TextField.Suffix> <Text>USD</Text> </TextField.Suffix> <TextField.SupportingText> <Text>Enter the amount</Text> </TextField.SupportingText> </TextField> </Host> ); }

Keyboard options

Use the keyboardOptions prop to configure the keyboard type, capitalization, auto-correct, and IME action.

KeyboardOptionsExample.tsx
import { useState } from 'react'; import { Host, TextField, Text } from '@expo/ui/jetpack-compose'; export default function KeyboardOptionsExample() { const [value, setValue] = useState(''); return ( <Host matchContents> <TextField onValueChange={setValue} singleLine keyboardOptions={{ keyboardType: 'email', capitalization: 'none', autoCorrectEnabled: false, imeAction: 'done', }}> <TextField.Label> <Text>Email</Text> </TextField.Label> </TextField> </Host> ); }

Keyboard actions

Use the keyboardActions prop to handle IME action button presses. The triggered callback depends on the imeAction set in keyboardOptions. Each callback receives the current text value.

KeyboardActionsExample.tsx
import { useState } from 'react'; import { Host, TextField, Text } from '@expo/ui/jetpack-compose'; export default function KeyboardActionsExample() { const [value, setValue] = useState(''); const [submitted, setSubmitted] = useState(''); return ( <Host matchContents> <TextField onValueChange={setValue} singleLine keyboardOptions={{ imeAction: 'search' }} keyboardActions={{ onSearch: text => setSubmitted(text), }}> <TextField.Label> <Text>Search</Text> </TextField.Label> </TextField> </Host> ); }

Error state

Set isError to display the text field in an error state. Combine with SupportingText to show an error message.

ErrorStateExample.tsx
import { useState } from 'react'; import { Host, OutlinedTextField, Text } from '@expo/ui/jetpack-compose'; export default function ErrorStateExample() { const [value, setValue] = useState(''); const hasError = value.length > 0 && !value.includes('@'); return ( <Host matchContents> <OutlinedTextField onValueChange={setValue} isError={hasError} singleLine> <OutlinedTextField.Label> <Text>Email</Text> </OutlinedTextField.Label> <OutlinedTextField.SupportingText> <Text>{hasError ? 'Please enter a valid email' : 'Required'}</Text> </OutlinedTextField.SupportingText> </OutlinedTextField> </Host> ); }

Imperative ref

Use a ref to imperatively set text, focus, or blur the text field.

ImperativeRefExample.tsx
import { useRef, useState } from 'react'; import { Host, TextField, TextFieldRef, Button, Row, Text, Column } from '@expo/ui/jetpack-compose'; import { padding } from '@expo/ui/jetpack-compose/modifiers'; export default function ImperativeRefExample() { const ref = useRef<TextFieldRef>(null); const [value, setValue] = useState(''); return ( <Host matchContents> <Column> <TextField ref={ref} onValueChange={setValue} singleLine> <TextField.Label> <Text>Name</Text> </TextField.Label> </TextField> <Row horizontalArrangement={{ spacedBy: 8 }} modifiers={[padding(8, 0, 0, 0)]}> <Button onClick={() => ref.current?.setText('Hello!')}> <Text>Set text</Text> </Button> <Button onClick={() => ref.current?.focus()}> <Text>Focus</Text> </Button> <Button onClick={() => ref.current?.blur()}> <Text>Blur</Text> </Button> </Row> </Column> </Host> ); }

API

import { TextField, OutlinedTextField } from '@expo/ui/jetpack-compose';

Components

OutlinedTextField

Android

Type: React.Element<OutlinedTextFieldProps>

A Material3 OutlinedTextField with a transparent background and border outline.

OutlinedTextFieldProps

colors

Android
Optional • Type: TextFieldColors

Inherited Props

TextField

Android

Type: React.Element<TextFieldProps>

A Material3 TextField.

TextFieldProps

colors

Android
Optional • Type: TextFieldColors

Inherited Props

Types

TextFieldCapitalization

Android

Literal Type: string

Acceptable values are: 'none' | 'characters' | 'words' | 'sentences'

TextFieldColors

Android

Colors for TextField and OutlinedTextField. Maps to TextFieldColors in Compose, shared by both variants.

PropertyTypeDescription
cursorColor(optional)ColorValue
-
disabledContainerColor(optional)ColorValue
-
disabledIndicatorColor(optional)ColorValue
-
disabledLabelColor(optional)ColorValue
-
disabledLeadingIconColor(optional)ColorValue
-
disabledPlaceholderColor(optional)ColorValue
-
disabledPrefixColor(optional)ColorValue
-
disabledSuffixColor(optional)ColorValue
-
disabledSupportingTextColor(optional)ColorValue
-
disabledTextColor(optional)ColorValue
-
disabledTrailingIconColor(optional)ColorValue
-
errorContainerColor(optional)ColorValue
-
errorCursorColor(optional)ColorValue
-
errorIndicatorColor(optional)ColorValue
-
errorLabelColor(optional)ColorValue
-
errorLeadingIconColor(optional)ColorValue
-
errorPlaceholderColor(optional)ColorValue
-
errorPrefixColor(optional)ColorValue
-
errorSuffixColor(optional)ColorValue
-
errorSupportingTextColor(optional)ColorValue
-
errorTextColor(optional)ColorValue
-
errorTrailingIconColor(optional)ColorValue
-
focusedContainerColor(optional)ColorValue
-
focusedIndicatorColor(optional)ColorValue
-
focusedLabelColor(optional)ColorValue
-
focusedLeadingIconColor(optional)ColorValue
-
focusedPlaceholderColor(optional)ColorValue
-
focusedPrefixColor(optional)ColorValue
-
focusedSuffixColor(optional)ColorValue
-
focusedSupportingTextColor(optional)ColorValue
-
focusedTextColor(optional)ColorValue
-
focusedTrailingIconColor(optional)ColorValue
-
unfocusedContainerColor(optional)ColorValue
-
unfocusedIndicatorColor(optional)ColorValue
-
unfocusedLabelColor(optional)ColorValue
-
unfocusedLeadingIconColor(optional)ColorValue
-
unfocusedPlaceholderColor(optional)ColorValue
-
unfocusedPrefixColor(optional)ColorValue
-
unfocusedSuffixColor(optional)ColorValue
-
unfocusedSupportingTextColor(optional)ColorValue
-
unfocusedTextColor(optional)ColorValue
-
unfocusedTrailingIconColor(optional)ColorValue
-

TextFieldImeAction

Android

Literal Type: string

Acceptable values are: 'default' | 'none' | 'go' | 'search' | 'send' | 'previous' | 'next' | 'done'

TextFieldKeyboardActions

Android

Keyboard actions matching Compose KeyboardActions. The triggered callback depends on the imeAction in keyboardOptions.

PropertyTypeDescription
onDone(optional)(value: string) => void
-
onGo(optional)(value: string) => void
-
onNext(optional)(value: string) => void
-
onPrevious(optional)(value: string) => void
-
onSearch(optional)(value: string) => void
-
onSend(optional)(value: string) => void
-

TextFieldKeyboardOptions

Android

Keyboard options matching Compose KeyboardOptions.

PropertyTypeDescription
autoCorrectEnabled(optional)boolean
Default:true
capitalization(optional)TextFieldCapitalization
Default:'none'
imeAction(optional)TextFieldImeAction
Default:'default'
keyboardType(optional)TextFieldKeyboardType
Default:'text'

TextFieldKeyboardType

Android

Literal Type: string

Acceptable values are: 'text' | 'number' | 'email' | 'phone' | 'decimal' | 'password' | 'ascii' | 'uri' | 'numberPassword'

TextFieldRef

Android

Can be used for imperatively setting text and focus on the TextField component.

PropertyTypeDescription
blur() => Promise<void>
-
focus() => Promise<void>
-
setText(newText: string) => Promise<void>
-