Components

OTP Input

otp x digit

One-time-password input with individual digit boxes. From Bundui.

otpinputdigitbundui

Code

input-otp.tsx
"use client";
import { useRef, useState } from "react";

export function OTPInput({ length = 4, onComplete }: { length?: number; onComplete?: (code: string) => void }) {
  const [values, setValues] = useState<string[]>(() => Array(length).fill(""));
  const refs = useRef<(HTMLInputElement | null)[]>([]);
  function set(i: number, v: string) {
    const digit = v.replace(/\D/g, "").slice(-1);
    const next = [...values];
    next[i] = digit;
    setValues(next);
    if (digit && i < length - 1) refs.current[i + 1]?.focus();
    if (next.every(Boolean)) onComplete?.(next.join(""));
  }
  return (
    <div className="flex gap-2">
      {values.map((v, i) => (
        <input key={i} ref={(el) => { refs.current[i] = el; }} value={v} inputMode="numeric" maxLength={1}
          onChange={(e) => set(i, e.target.value)}
          onKeyDown={(e) => { if (e.key === "Backspace" && !values[i] && i > 0) refs.current[i - 1]?.focus(); }}
          className="size-12 rounded-lg border border-border bg-surface text-center font-mono text-lg outline-none focus:border-brand/60" />
      ))}
    </div>
  );
}

Use it in another build

Paste the code into a component file, keep your project tokens (background, brand, radius) and it themes itself. Or tell Claude Code: “add the OTP Input component and wire it to my accent.”