---
modificationDate: April 28, 2026
title: TextField
description: A SwiftUI TextField component for text input.
sourceCodeUrl: 'https://github.com/expo/expo/tree/main/packages/expo-ui'
packageName: '@expo/ui'
platforms: ['ios', 'tvos']
---

<AgentInstructions>

## Submitting Feedback

If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:

curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/v55.0.0/sdk/ui/swift-ui/textfield/","feedback":"🤖 Agent feedback: <specific, actionable description>"}'

Only submit when you have something specific and actionable to report.

</AgentInstructions>

# TextField

A SwiftUI TextField component for text input.
iOS, tvOS

> For the complete documentation index, see [llms.txt](/llms.txt). Use this file to discover all available pages.

Expo UI TextField matches the official SwiftUI [TextField API](https://developer.apple.com/documentation/swiftui/textfield) and supports single-line and multiline input, keyboard configuration, submit handling, and an imperative `ref` for programmatic control.

## Installation

```sh
npx expo install @expo/ui
```

If you are installing this in an [existing React Native app](/bare/overview), make sure to [install `expo`](/bare/installing-expo-modules) in your project.

## Usage

### Basic text field

```tsx
import { useState } from 'react';
import { Host, TextField } from '@expo/ui/swift-ui';

export default function BasicTextFieldExample() {
  const [value, setValue] = useState('');

  return (
    <Host matchContents>
      <TextField placeholder="Username" onValueChange={setValue} />
    </Host>
  );
}
```

### Multiline text field

Set `axis="vertical"` to allow the text field to expand vertically. Use the [`lineLimit`](/versions/v55.0.0/sdk/ui/swift-ui/modifiers#linelimit) modifier to control the visible line count. When using `Host matchContents`, add `fixedSize({ horizontal: false, vertical: true })` so the text field accepts the parent's width while using its ideal height.

```tsx
import { useState } from 'react';
import { Host, TextField } from '@expo/ui/swift-ui';
import { lineLimit, fixedSize } from '@expo/ui/swift-ui/modifiers';

export default function MultilineTextFieldExample() {
  const [value, setValue] = useState('');

  return (
    <Host matchContents>
      <TextField
        axis="vertical"
        placeholder="Tell us about yourself..."
        onValueChange={setValue}
        modifiers={[lineLimit(5), fixedSize({ horizontal: false, vertical: true })]}
      />
    </Host>
  );
}
```

### Keyboard type

Use the [`keyboardType`](/versions/v55.0.0/sdk/ui/swift-ui/modifiers#keyboardtypekeyboardtype) modifier to display a specific keyboard layout.

```tsx
import { useState } from 'react';
import { Host, TextField } from '@expo/ui/swift-ui';
import { keyboardType, autocorrectionDisabled } from '@expo/ui/swift-ui/modifiers';

export default function KeyboardTypeExample() {
  const [value, setValue] = useState('');

  return (
    <Host matchContents>
      <TextField
        placeholder="Email"
        onValueChange={setValue}
        modifiers={[keyboardType('email-address'), autocorrectionDisabled()]}
      />
    </Host>
  );
}
```

### Submit handling

Use the [`submitLabel`](/versions/v55.0.0/sdk/ui/swift-ui/modifiers#submitlabelsubmitlabel) modifier to customize the return key and [`onSubmit`](/versions/v55.0.0/sdk/ui/swift-ui/modifiers#onsubmithandler) to handle the submit action.

```tsx
import { useState } from 'react';
import { Host, TextField } from '@expo/ui/swift-ui';
import { submitLabel, onSubmit } from '@expo/ui/swift-ui/modifiers';

export default function SubmitHandlingExample() {
  const [value, setValue] = useState('');

  return (
    <Host matchContents>
      <TextField
        placeholder="Search..."
        onValueChange={setValue}
        modifiers={[submitLabel('search'), onSubmit(() => console.log('Submitted:', value))]}
      />
    </Host>
  );
}
```

### Imperative ref

Use a `ref` to imperatively set text, focus, blur, or select text.

```tsx
import { useRef } from 'react';
import { Host, TextField, TextFieldRef, Button, HStack, VStack } from '@expo/ui/swift-ui';
import { buttonStyle } from '@expo/ui/swift-ui/modifiers';

export default function ImperativeRefExample() {
  const ref = useRef<TextFieldRef>(null);

  return (
    <Host matchContents>
      <VStack>
        <TextField ref={ref} defaultValue="Select me!" placeholder="Imperative field" />
        <HStack spacing={12}>
          <Button
            modifiers={[buttonStyle('bordered')]}
            onPress={() => ref.current?.focus()}
            label="Focus"
          />
          <Button
            modifiers={[buttonStyle('bordered')]}
            onPress={() => ref.current?.blur()}
            label="Blur"
          />
          <Button
            modifiers={[buttonStyle('bordered')]}
            onPress={() => ref.current?.setText('SwiftUI rocks!')}
            label="Set Text"
          />
          <Button
            modifiers={[buttonStyle('bordered')]}
            onPress={() => ref.current?.setSelection(0, 7)}
            label="Select"
          />
        </HStack>
      </VStack>
    </Host>
  );
}
```

## API

```tsx
import { TextField } from '@expo/ui/swift-ui';
```

## Component

### `TextField`

Supported platforms: iOS, tvOS.

Type: React.[Element](https://www.typescriptlang.org/docs/handbook/jsx.html#function-component)<[TextFieldProps](#textfieldprops)\>

Renders a SwiftUI `TextField`.

TextFieldProps

### `autoFocus`

Supported platforms: iOS, tvOS.

Optional • Type: `boolean` • Default: `false`

If true, the text field will be focused automatically when mounted.

### `axis`

Supported platforms: iOS, tvOS.

Optional • Literal type: `string` • Default: `'horizontal'`

The axis along which the text field grows when content exceeds a single line.

-   `'horizontal'` — single line (default).
-   `'vertical'` — expands vertically for multiline content. Use `lineLimit` modifier to cap visible lines.

Acceptable values are: `'horizontal'` | `'vertical'`

### `defaultValue`

Supported platforms: iOS, tvOS.

Optional • Type: `string`

Initial value displayed when mounted. Uncontrolled — change `key` to reset.

### `onFocusChange`

Supported platforms: iOS, tvOS.

Optional • Type: `(focused: boolean) => void`

A callback triggered when the field gains or loses focus.

### `onSelectionChange`

Supported platforms: iOS 18.0+ tvos 18.0+.

Optional • Type: `({ start, end }: { end: number, start: number }) => void`

A callback triggered when user selects text in the TextField.

### `onValueChange`

Supported platforms: iOS, tvOS.

Optional • Type: `(value: string) => void`

A callback triggered when the text value changes.

### `placeholder`

Supported platforms: iOS, tvOS.

Optional • Type: `string`

A text that is displayed when the field is empty.

### `ref`

Supported platforms: iOS, tvOS.

Optional • Type: Ref<[TextFieldRef](#textfieldref)\>

#### Inherited Props

-   [CommonViewModifierProps](/versions/v55.0.0/sdk/ui/swift-ui/modifiers)

## Types

### `TextFieldRef`

Supported platforms: iOS, tvOS.

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

| Property | Type | Description |
| --- | --- | --- |
| blur | () => [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<void\> | - |
| focus | () => [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<void\> | - |
| setSelection | (start: number, end: number) => [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<void\> | Supported platforms: iOS 18.0+ tvos 18.0+. Programmatically select text using start and end indices. |
| setText | (newText: string) => [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<void\> | - |
