Components

OTP Input

A multi-field input for entering one-time passwords (OTP) with support for auto-focus, paste handling, labels, and hints.

Try typing or pasting a 4-digit number.

A divider appears automatically after the first 3 digits.

Current value: —

Installation

Usage

import { OtpInput } from "@/registry/core/otp-input";

export default function Example() {
  const [value, setValue] = useState("");

  return (
    <OtpInput
      label="Verification Code"
      digitLength={6}
      value={value}
      onChange={e => setValue(e.target.value)}
      hint="Enter the 6-digit code sent to your email."
    />
  );
}

API Reference

OtpInput

Extends input element props (except value).

PropTypeDefaultDescription
digitLength4 | 64Number of OTP fields
labelstring-Optional field label
hintstring-Helper text shown below the field
valuestring-Controlled OTP value (auto-synced to fields)
disabledbooleanfalseDisable all OTP inputs
classNamestring-Appended to each input element
onChangeReact.ChangeEventHandler-Returns concatenated OTP digits as one string

Behavior

  • Each box only accepts a single numeric digit
  • Auto-focus moves to the next box as you type
  • Backspace moves backward when empty
  • Handles paste of full OTP (e.g., pasting "123456")
  • Automatically pads if value prop is shorter

Accessibility

  • Each digit is a native <input type="text" />
  • Label is connected via htmlFor
  • Focus ring follows system and custom Tailgrids styles
  • Digits select their content when focused—making replacement easier
  • Screen readers read the label and each digit individually

Notes

  • The 6-digit layout includes a visual divider after the 3rd digit
  • Uses order to ensure correct visual grouping
  • Works seamlessly in controlled or uncontrolled mode
  • onChange always provides the full OTP value
  • Non-numeric keys are prevented except Backspace, Delete, Tab, Meta
  • Paste only works when the full OTP length matches exactly