---
title: OTP input
description: One cell per character of a one-time code, with paste and autofill.
---

```tsx
import { Field, OtpInput } from "@openperf/deft";

import { Preview } from "../../src/Preview";

export default function OtpInputBasic() {
  return (
    <Preview stack={true}>
      <Field.Root>
        <Field.Label>Label</Field.Label>
        <OtpInput.Root />
      </Field.Root>
    </Preview>
  );
}
```

- Use it for codes sent by email or SMS. For any other short value, use an [Input](/deft/components/input).
- Wrap it in a [Field](/deft/components/field): the label names the first cell, the others read as "Character 2 of 6".
- Pasting or autofilling a code fills every cell, and Backspace steps back. The first cell carries `autocomplete="one-time-code"`.
- `onValueComplete` fires once the last cell is filled, so the form can submit without a button press.

## Invalid

```tsx
import { Field, OtpInput } from "@openperf/deft";

import { Preview } from "../../src/Preview";

export default function OtpInputInvalid() {
  return (
    <Preview stack={true}>
      <Field.Root invalid={true}>
        <Field.Label>Label</Field.Label>
        <OtpInput.Root defaultValue="123456" />
        <Field.Error match={true}>Error message</Field.Error>
      </Field.Root>
    </Preview>
  );
}
```

Set `invalid` on the field when the server rejects the code. Keep the entered value so the person can see what they typed.

## API

| Prop | Type | Default | Description |
| - | - | - | - |
| `length?` | `number` | `6` | The number of cells. |
| `value?` | `string` | - | |
| `onValueChange?` | `(value: string) => void` | - | |
| `onValueComplete?` | `(value: string) => void` | - | |
| `validationType?` | `"numeric" \| "alpha" \| "alphanumeric" \| "none"` | `"numeric"` | |

Other props go to the Base UI `Root`. Built on Base UI [OTP Field](https://base-ui.com/react/components/otp-field).
