InputOTP
<InputOTP> is the one-time-code input — typically 6 digits for SMS / TOTP. Each character has its own slot; paste fills all slots; auto-advances on type. Adapted from shadcn’s canonical implementation; uses input-otp under the hood.
When to use
- SMS / TOTP verification codes during sign-in or 2FA.
- Email-link verification codes.
- Any short fixed-length numeric or alphanumeric code.
Don’t use InputOTP for: passwords (PasswordInput), free-form codes the user types from memory (use a regular Input), or long codes (≥ 8 chars feels gimmicky).
Six-digit (default)
Paste a 6-digit code anywhere — it fills all slots.
<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>Four-digit
<InputOTP maxLength={4}> <InputOTPGroup> <InputOTPSlot index={0} /> <InputOTPSlot index={1} /> <InputOTPSlot index={2} /> <InputOTPSlot index={3} /> </InputOTPGroup></InputOTP>Anatomy
InputOTP (root, manages the buffer) → one or more InputOTPGroups → each group contains InputOTPSlots indexed 0..maxLength-1. Use InputOTPSeparator between groups.
API
InputOTP
| Prop | Type | Default | Description |
|---|---|---|---|
maxLength * | number | — | Total slot count. |
value | string | — | Controlled value. Pair with onChange. |
onChange | (value: string) => void | — | Fires on every keystroke / paste. |
onComplete | (value: string) => void | — | Fires exactly once when value reaches maxLength. |
disabled | boolean | false | Disable all slots. |
pattern | string | — | RegExp source — restrict accepted characters (e.g. /^[0-9]+$/). |
InputOTPSlot
| Prop | Type | Default | Description |
|---|---|---|---|
index * | number | — | 0-based slot index. Must be unique and within [0, maxLength). |
className | string | — | Forwarded. |
InputOTPGroup and InputOTPSeparator accept native div attributes. The separator is decorative.
Design guidelines
✓ Do
- Use 6 digits for SMS / TOTP. Industry standard; users recognize it instantly.
- Set onComplete to auto-submit. Asking the user to also click Submit after typing 6 digits is friction.
- Pair with FormError below for invalid-code messages.
✗ Don't
- Use InputOTP for passwords. Slots advertise length and break password managers.
- Disable paste. Users paste from SMS / authenticator apps; they'll abandon if you block it.
- Show codes longer than 8 slots. Users mis-remember; reach for QR or magic link.
Accessibility
- The underlying
<input>is the focusable element; slots are visually-rich representations. - Keyboard: type to fill, Backspace to clear and back-step, Arrow keys to navigate.
- Paste anywhere in the OTP fills all slots (browser standard).
Related
Input— Free-form single-line.PasswordInput— For secrets.Form— react-hook-form integration.