---
url: https://native-shell.com/elements/input
description: "The native text field: controlled and uncontrolled text, keyboards, autofill, selection, multiline inputs and focus."
demo: https://native-shell.com/play/index.html#el-input
---

# Input

`<Input>` is a native text field: a UITextField (single line) or UITextView (`multiline`) on iOS and Mac Catalyst, an
EditText on Android. Typing, the caret, selection, autocorrection and autofill are the platform's own.

```tsx
import { Input, signal } from "nsh";

function NameField() {
  const name = signal("");
  return (
    <Input
      value={name()}
      onChangeText={(text) => name.set(text)}
      placeholder="Your name"
      autoCapitalize="words"
      returnKeyType="done"
      style={{ fontSize: 16, padding: 12, borderWidth: 1, borderColor: "#d0d7de", borderRadius: 8 }}
    />
  );
}
```

## Controlled and uncontrolled

- **Controlled**: pass `value` and update it in `onChangeText`. JS can rewrite what the user typed (trim it, format it):
  the text shows the edit at once and is corrected when the new `value` arrives. Each native edit carries a count, and a
  `value` from JS is applied only if it is based on the latest edit, so a slow JS turn never overwrites newer typing.
- **Uncontrolled**: pass `defaultValue` (or nothing) and read the text from `onChangeText` or `onSubmitEditing`.

Rules that must hold while the user types are props, answered natively without asking JS: `maxLength` limits the length
and `blurOnSubmit` decides what return does. See [forms and the keyboard](https://native-shell.com/docs/forms-and-keyboard.md).

## Props

Besides the [common props](https://native-shell.com/elements.md#common-props) (with `style` typed as `TextStyle`: font, color, alignment and the
view styles apply):

### Text

| Prop | Type | Default | Description |
|---|---|---|---|
| `value` | `string` | | The text, controlled by JS. |
| `defaultValue` | `string` | | The initial text. |
| `placeholder` | `string` | | Shown while the input is empty. |
| `placeholderTextColor` | `ColorValue` | | The placeholder's color. |
| `multiline` | `boolean` | `false` | Several lines; return inserts a line break. |
| `maxLength` | `number` | | The most characters the user can enter. |
| `editable` | `boolean` | `true` | The user can change the text. |
| `secureTextEntry` | `boolean` | `false` | The text is hidden (passwords). |
| `allowFontScaling` | `boolean` | `true` | Follow the system text size. |
| `maxFontSizeMultiplier` | `number` | `0` | The upper bound of the system scale (0 is none). |

### Keyboard

| Prop | Type | Default | Description |
|---|---|---|---|
| `keyboardType` | `"default" \| "number-pad" \| "numeric" \| "decimal-pad" \| "email-address" \| "phone-pad" \| "url"` | `"default"` | The keyboard layout. |
| `returnKeyType` | `"default" \| "done" \| "go" \| "next" \| "search" \| "send"` | `"default"` | The label of the return key. |
| `autoCapitalize` | `"none" \| "sentences" \| "words" \| "characters"` | `"sentences"` | Automatic capitalization. |
| `autoCorrect` | `boolean` | `true` | The system's corrections. |
| `autoComplete` | `AutoComplete \| TextContentType` | | What the input holds, for autofill: `"username"`, `"current-password"`, `"new-password"`, `"one-time-code"`, `"email"`, `"tel"`, `"postal-code"`, `"cc-number"`, `"off"`, … |
| `blurOnSubmit` | `boolean` | `true` | Return unfocuses a single-line input; `false` keeps the keyboard up (e.g. to send several messages). |
| `autoFocus` | `boolean` | `false` | Focused when it appears. |

### Caret and selection

| Prop | Type | Description |
|---|---|---|
| `caretHidden` | `boolean` | No caret is drawn. |
| `selectionColor` | `ColorValue` | The color of the caret and the selection. |
| `selection` | `{ start: number; end?: number }` | The controlled selection, in UTF-16 units; `end` defaults to `start` (a caret). |

### iOS

| `ios` key | Type | Description |
|---|---|---|
| `textContentType` | `AutoComplete \| TextContentType` | iOS's names for `autoComplete` (`"oneTimeCode"`, `"newPassword"`, …). |
| `inputAccessoryViewID` | `string` | The `nativeID` of an `InputAccessoryView` ([`nsh/ios`](https://native-shell.com/modules/nsh-ios.md)) shown over the keyboard while the input has focus. |

```tsx
<Input autoComplete="one-time-code" keyboardType="number-pad" ios={{ textContentType: "oneTimeCode" }} />
```

## Events

| Event | Payload | When |
|---|---|---|
| `onChangeText` | `(text: string)` | The user changed the text. |
| `onSubmitEditing` | `{ text }` | The return key was pressed (single line). |
| `onFocus` / `onBlur` | none | The input gained / lost focus. |
| `onSelectionChange` | `{ start, end }` | The caret or selection moved (UTF-16 units). |
| `onKeyPress` | `{ key }` | Before the text changes: `key` is the typed text, `"Backspace"` or `"Enter"`. |
| `onContentSizeChange` | `{ width, height }` | The size of the text changed (at the input's width when multiline). |

A multiline input that grows with its text:

```tsx
const height = signal(40);
<Input
  multiline
  onContentSizeChange={(e) => height.set(Math.min(120, Math.max(40, e.height + 16)))}
  style={{ height: height(), paddingHorizontal: 12, paddingVertical: 8 }}
/>;
```

## Ref methods

| Method | Description |
|---|---|
| `focus()` | Focuses the input and shows the keyboard. |
| `blur()` | Unfocuses it. |
| `setSelection(start, end?)` | Selects `start..end` (UTF-16 units); a caret without `end`. |

Moving focus to the next field on return:

```tsx
let password!: YNode;
<>
  <Input returnKeyType="next" onSubmitEditing={() => password.focus()} />
  <Input ref={password} secureTextEntry autoComplete="current-password" />
</>;
```

`Keyboard.dismiss()` from [`nsh/ui/mobile`](https://native-shell.com/components/keyboard.md) hides the keyboard whichever input has it.

## Platform notes

- Inputs inside a [`<Scroll>`](https://native-shell.com/elements/scroll.md#keyboard) are kept clear of the keyboard natively. Elsewhere use
  `KeyboardAvoidingView`.
- `disabled` disables the input as well as applying `disabled:` classes.
- `inputAccessoryViewID` has no effect on Android, which has no keyboard accessory bar.
