Skip to content
OpenPerf
Esc
↑↓navigate↵open⌘Jpreview
On this page

OTP input

One cell per character of a one-time code, with paste and autofill.

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.
  • Wrap it in a 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

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

PropType
length?number

The number of cells.

Typenumber
Default6
value?string
Typestring
onValueChange?(value: string) => void
Type(value: string) => void
onValueComplete?(value: string) => void
Type(value: string) => void
validationType?"numeric" | "alpha" | "alphanumeric" | "none"
Type"numeric" | "alpha" | "alphanumeric" | "none"
Default"numeric"

Other props go to the Base UI Root. Built on Base UI OTP Field.

Was this page helpful?