# OTP input

> A verification code field where digits pop in, a pending check breathes, success ripples across the cells and a wrong code shakes and clears.

- Type: Component (inputs)
- Access: Free, open source (MIT)
- Page: https://goodui.dev/native/components/otp-input
- Markdown: https://goodui.dev/native/components/otp-input.md
- Registry item: https://goodui.dev/native/r/otp-input.json
- Dependencies: react-native-reanimated
- Keywords: react native otp input, verification code, one time code, sms code autofill, pin input, 2fa code

## When to use

- Sign in and sign up verification, two factor codes, email confirmation codes.

## When not to use

- Passwords or PINs that must stay hidden: use a secure text field.
- Codes with letters: this field accepts digits only.

## Installation

With the shadcn CLI (needs a components.json in the Expo app), then `npx expo install --fix` so native dependencies match your Expo SDK. The foundation comes along the first time.

```bash
npx shadcn@latest add https://goodui.dev/native/r/otp-input.json
npx expo install --fix
```

The component lands in `components/goodui-native/otp-input/` and imports the foundation from `components/goodui-native/foundation/` with relative paths; it also installs locale.

Built-in strings follow `<GooduiLocaleProvider>` (one [language pack](https://goodui.dev/native/r/locale-tr.json) translates the whole kit); the `labels` prop overrides them for one instance.

## Usage

```tsx
import { OtpInput } from "@/components/goodui-native/otp-input/otp-input";

<OtpInput autoFocus onComplete={(code) => api.verify(code)} />
```

## API reference

### OtpInput

`import { OtpInput } from "@/components/goodui-native/otp-input/otp-input";`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `length` | `number` | `6` | Number of digits. Default 6. |
| `onComplete` (required) | `(code: string) => unknown` | – | Called when every cell is filled. Return a promise: resolve to accept the code, reject to shake, clear and try again. |
| `onChange` | `(code: string) => void` | – | Called on every change. |
| `autoFocus` | `boolean` | `false` | Focus the field and open the keyboard on mount. |
| `errorText` | `string` | – | Message under the cells after a rejected code. Same as `labels.error`. |
| `labels` | `Partial<OtpInputLabels>` | – | Overrides for the built-in strings; a GooduiLocaleProvider pack sets them app-wide. |
| `accessibilityLabel` | `string` | – | Overrides the label read by screen readers. |
| `style` | `StyleProp<ViewStyle>` | – | Style for the outer container. |
| `testID` | `string` | – | Identifier for end-to-end tests. |

## Accessibility

- One real TextInput owns the keyboard, paste, iOS one-time-code and Android SMS autofill, and the screen reader label ('Verification code, 6 digits').
- The cells are hidden from screen readers. Results are announced.

## Motion

- Digits land with a small pop on the bouncy spring; the active cell has a blinking caret and an accent border.
- While a returned promise is pending the cells breathe in a cascade.
- Success ripples a scale wave across the cells and tints them green; an error tints them red and shakes the row.
- Reduced motion: no pop, wave, breathing or shake; colors still change.

## Haptics

- success when the code is accepted
- error when it is rejected

## Performance

- Each cell animates on the UI thread; typing re-renders only the cells.

## Notes for AI

- Return a promise from onComplete: resolve to accept, reject to shake and clear. Do not manage error state yourself.
- Do not wrap it in another TextInput or add your own keyboard handling.

## Related

- [Button](https://goodui.dev/native/components/button.md): A press-responsive button with haptics that runs async actions on its own: it gathers into a spinner, then opens into a success or error state.

## Guidance for AI tools

OTP input: A verification code field where digits pop in, a pending check breathes, success ripples across the cells and a wrong code shakes and clears. Use only the documented props. Keep accessibility, reduced motion and both color schemes intact when adapting it.

Full library index: https://goodui.dev/native/llms.txt
