OTP input
A six digit verification flow with paste support and keyboard navigation.
pnpm dlx shadcn@latest add @uiarc/otp-inputPattern · live
- Verification codes from email or SMS.
- Two-factor authentication code entry.
- Use password-field for secrets people type from memory.
- Use input for any other text.
Installation
Add OTP input with the shadcn CLI, or copy the source by hand.
pnpm dlx shadcn@latest add @uiarc/otp-inputAdds the block and its local dependencies, and installs motion. First time? Add the @uiarc registry to components.json, or use the full URL:
Usage
Use it as part of verification after you have sent a code. Validate the code on your server.
example.tsx
import { useState } from "react";import { OtpInput } from "@/registry/components/otp-input/otp-input"; export function VerifyCode() { const [code, setCode] = useState(""); return ( <OtpInput label="Verification code" description="We sent a 6-digit code to your email." value={code} onChange={next => { setCode(next); if (next.length === 6) verify(next); }} autoFocus /> );}Built fromInputKeyboard navigationValidation
OtpInput
A row of single-character inputs for one-time codes, with paste fill, a gliding focus ring, and animated helper and error copy.
PropTypeDefaultDescription
labelRequiredstring–Visible label and group name; each slot is labelled with it plus its position.lengthnumber6Number of slots.valuestring""Current code. Controlled: update it from onChange.onChange(value: string) => void–Called with the full code after every edit or paste.descriptionstring–Helper text below the slots.errorstring–Error text. Sets aria-invalid and shakes the row once when it changes.inputMode"numeric" | "text""numeric"numeric strips non-digits.autoFocusbooleanfalseFocuses the first slot on mount.disabledbooleanfalseDisables every slot.classNamestring–Merged onto the field wrapper.- 0-9orcharacters
- Fills the slot and moves to the next one.
- ArrowLeftorArrowRight
- Moves between slots.
- Backspace
- On an empty slot, clears the previous one and moves back.
- Delete
- Clears the current slot.
- Cmd/Ctrl+V
- Pastes a code across the slots from the focused one.
- Slots sit in a labelled role=group, each with an aria-label like Verification code, digit 1 of 6.
- Helper and error text are linked with aria-describedby; the error uses role=alert and sets aria-invalid.
- The first slot uses autocomplete one-time-code so browsers can offer SMS codes.
- Typed characters rise into the slot and unblur; a paste lands as a short left-to-right wave.
- One focus ring glides between slots, and a new error nudges the row side to side once.
- Reduced motion removes the glide, shake, and blur and uses instant fades.
- Slots are 42px wide and can shrink with max-width 100%; below 360px gaps tighten and slots drop to 44px tall.
- The first slot uses autocomplete one-time-code, so iOS and Android can offer SMS codes.
- numeric inputMode brings up the number pad on phones.
- Only a handful of inputs plus one gliding ring; a ResizeObserver springs the message height.
Notes for AI
Give your coding assistant the Markdown reference instead of screenshots.
- Use for verification and two-factor codes. Use input or password-field for anything else.
- It is controlled: keep value in state and submit when value.length equals length. There is no default export, so import it by name.
The full library index for assistants is at /llms.txt.