OTP input
A six digit verification flow with paste support and keyboard navigation.
Preview
OTP input preview
Live · keyboard ready
Verification code
When to use
- Verification codes from email or SMS.
- Two-factor authentication code entry.
When not to use
- Use password-field for secrets people type from memory.
- Use input for any other text.
shadcn CLI
Also installs (1)
- manicat-foundation
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "otp-input",
"type": "registry:block",
"title": "OTP input",
"description": "A six digit verification flow with paste support and keyboard navigation.",
"categories": [
"blocks"
],
"dependencies": [
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json"
],
"files": [
{
"path": "registry/components/otp-input/otp-input.tsx",
"type": "registry:component",
"target": "@components/manicat/otp-input/otp-input.tsx"
},
{
"path": "registry/components/otp-input/otp-input.module.css",
"type": "registry:component",
"target": "@components/manicat/otp-input/otp-input.module.css"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/blocks/otp-input",
"meta": {
"tier": "free",
"kind": "block",
"docs": "https://manicat.viraza.net/components/blocks/otp-input",
"markdown": "https://uiarc.dev/components/blocks/otp-input/markdown"
}
}Usage
Install the component, then copy this into your app. Change the content and the props to fit your screen.
example.tsxtsx
"use client";
import { useState } from "react";
import { OtpInput } from "@/components/manicat/otp-input/otp-input";
export function OtpInputExample() {
const [value, setValue] = useState("");
return <OtpInput label="Verification code" length={6} value={value} onChange={setValue} />;
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
Verify your email Six digits, auto-advancing, with paste support, then a confirm button.
Verify your email
Six digits, auto-advancing, with paste support, then a confirm button. preview
Live · keyboard ready
Verification code
verify-your-email-six-digits-auto-advancing-with-paste-support-then-a-confirm-button-.tsxtsx
Keyboard interactions
| Keys | Action |
|---|---|
| 0-9 / characters | Fills the slot and moves to the next one. |
| ArrowLeft / ArrowRight | 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. |
Accessibility
- 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.
Motion
- 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.
Responsive behavior
- 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.
Performance
- Only a handful of inputs plus one gliding ring; a ResizeObserver springs the message height.
Notes for AI
- 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.