Components / Inputs

OtpInput

A six digit verification flow with paste support and keyboard navigation.

Install

npx shadcn@latest add https://irisui.dev/r/otp-input.json
import { OtpInput } from "@/components/iris/otp-input/otp-input";
Registry item otp-inputBrings in foundationRegistry JSON

Preview

OtpInput

A segmented one-time-code field with paste support, keyboard navigation and a single sliding focus ring.

When to use

  • Verifying an email or phone (such as an OpsisID phone check), two-factor sign-in, or confirming a sensitive action with a short code.
  • Short fixed-length codes, numeric by default or alphanumeric with inputMode="text".
  • Not for passwords or long tokens; use PasswordStrength or Input.

Usage

import { OtpInput } from "@/components/iris/otp-input/otp-input";

const [code, setCode] = useState("");
h(OtpInput, {
  label: "Verification code",
  description: "Code sent to your phone, valid for 10 min.",
  value: code,
  onChange: (next) => {
    setCode(next);
    if (next.length === 6) verify(next);
  },
  autoFocus: true,
});

Props

Prop Type Default Description
label string required Visible label and group name; each slot adds its position ("digit 1 of 6").
length number 6 Number of slots.
value string "" Current code (controlled; update from onChange).
onChange (value: string) => void – Full code after every edit or paste.
description string – Helper text below the slots.
error string – Error text; sets aria-invalid and shakes the row once when it changes.
inputMode "numeric" | "text" "numeric" numeric strips non-digits.
autoFocus boolean false Focus the first slot on mount.
disabled boolean false Disables every slot.
className string – Merged onto the field wrapper.

Notes

  • Keyboard: typing fills and advances; arrows move between slots; Backspace on an empty slot clears the previous one; Delete clears the current one; Mod+V pastes across slots.
  • The first slot supports one-time-code autocomplete so browsers and phones can offer SMS codes. Errors are announced as alerts.
  • Reduced motion removes the slide, shake and blur in favour of fades.
  • The slots sit in a fieldset named by label. Filled slots use an accent border over accent-tint; the focus ring is accent-ink; errors use red.