OTP input
FreeA segmented field for one-time codes with paste support and status.
pnpm dlx shadcn@latest add https://caliperui.site/r/otp-input.json0 of 6 digits.
Try 123456.
When to use #
Use it for
- Sign-in and verification codes of four to eight digits.
- You want success and error states on the whole code.
Skip it when
- The code is long or alphanumeric free text; use an input.
Installation #
terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/otp-input.json
Adds its 4 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.
Usage #
This is the code behind the preview above.
example.tsx
import { useState } from "react" import { OtpInput } from "@/components/ui/otp-input" export function VerifyCode() { const [code, setCode] = useState(""); const status = code.length < 6 ? "idle" : code === "123456" ? "success" : "error"; return ( <div className="grid justify-items-center gap-2"> <OtpInput label="Sign-in code" value={code} onValueChange={setCode} status={status} /> <p className="text-sm text-muted-foreground">Try 123456.</p> </div> ); }
API reference #
OtpInput
component
PropTypeDefaultDescription
labelstring"One-time code"
lengthnumber6
valuestring—
defaultValuestring""
onValueChange((value: string) => void)—
status"success" | "error" | "idle""idle"
messagestring—Replaces the status line, e.g. why a code was refused or “Checking the code…”.
disabledboolean—
namestring—
classNamestring—
Accessibility #
It exposes status semantics, with aria-label and aria-hidden kept in step with state. Changes that matter are announced through a live region.
KeyBehaviour
BackspaceRemoves the previous character or item.
←Moves to the previous item or value.
→Moves to the next item or value.
Motion #
It declares no animation in its component source. Any transition comes from its stylesheet, which uses the duration tokens that collapse to instant under prefers-reduced-motion.