Input OTP
A one-time password input built on the input-otp library.
When to use
For fixed-length codes typed or pasted in from another channel: two-factor confirmation, email verification, a short PIN. Anything of variable length is an Input, and a long-lived secret belongs in a password Input, not here.
Platform notes
Visually it is a row of div slots, but the real control is a single hidden input, so react-hook-form binds one string and pasting the whole code works without extra handling. Slots share edges (border-y border-r with first:border-l), all on --input, and the active slot lifts to --ring, so a className that adds a full border will double every divider line. The blinking caret uses animate-caret-blink, and the theme's base.css already collapses animations under prefers-reduced-motion, so nothing extra is required for that. Since the slots are not labelled elements, label the group and put the instruction in a FieldDescription, both strings coming from react-i18next.
Install
npx shadcn@latest add input-otpCode
import {
InputOTP,
InputOTPGroup,
InputOTPSeparator,
InputOTPSlot,
} from "@/components/ui/input-otp";
export function InputOtpDemo() {
return (
<InputOTP maxLength={6}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
);
}