- Gallery
- Forms & Input
- OTP Input
New
OTP Input
6-digit OTP/verification code input with auto-focus and paste support.
Forms & Inputotpverificationcodeinput2fa
Dependencies
Other dependencies:
@/components/ui/card@/components/ui/button@/components/ui/input
How to use this component
Copy the code below into your project. Make sure you have the required shadcn/ui dependencies installed. Then import and use the component in your pages or layouts.
Code
1"use client";23import { useState, useRef, useEffect } from 'react';4import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';5import { Button } from '@/components/ui/button';6import { Input } from '@/components/ui/input';78export default function OTPInput() {9 const [values, setValues] = useState(['', '', '', '', '', '']);10 const inputRefs = useRef<(HTMLInputElement | null)[]>([]);1112 useEffect(() => {13 inputRefs.current[0]?.focus();14 }, []);1516 const handleChange = (index: number, value: string) => {17 const newValues = [...values];18 newValues[index] = value.slice(-1);19 setValues(newValues);2021 if (value && index < 5) {22 inputRefs.current[index + 1]?.focus();23 }24 };2526 const handleKeyDown = (index: number, e: React.KeyboardEvent<HTMLInputElement>) => {27 if (e.key === 'Backspace' && !values[index] && index > 0) {28 inputRefs.current[index - 1]?.focus();29 }30 };3132 const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {33 e.preventDefault();34 const pastedData = e.clipboardData.getData('text').slice(0, 6).split('');35 if (pastedData.every(char => /^[0-9]$/.test(char))) {36 const newValues = [...values];37 pastedData.forEach((char, i) => {38 if (i < 6) newValues[i] = char;39 });40 setValues(newValues);41 const nextEmptyIndex = newValues.findIndex(v => v === '');42 inputRefs.current[nextEmptyIndex === -1 ? 5 : nextEmptyIndex]?.focus();43 }44 };4546 const handleVerify = () => {47 const code = values.join('');48 if (code.length === 6) {49 alert(`Verified code: ${code}`);50 }51 };5253 return (54 <Card className="w-full max-w-md mx-auto">55 <CardHeader className="text-center">56 <CardTitle>Verification Code</CardTitle>57 <p className="text-sm text-muted-foreground">58 Enter the 6-digit code sent to your email59 </p>60 </CardHeader>61 <CardContent className="space-y-6">62 <div className="flex justify-center gap-2">63 {values.map((value, index) => (64 <Input65 key={index}66 ref={el => inputRefs.current[index] = el}67 type="text"68 inputMode="numeric"69 maxLength={1}70 value={value}71 onChange={e => handleChange(index, e.target.value)}72 onKeyDown={e => handleKeyDown(index, e)}73 onPaste={handlePaste}74 className="w-12 h-12 text-center text-2xl font-mono"75 />76 ))}77 </div>7879 <Button onClick={handleVerify} className="w-full" size="lg">80 Verify81 </Button>8283 <div className="text-center space-y-2">84 <p className="text-sm text-muted-foreground">85 Didn't receive the code?{' '}86 <button className="text-primary hover:underline font-medium">87 Resend88 </button>89 </p>90 <p className="text-xs text-muted-foreground">91 Resend in 00:3092 </p>93 </div>94 </CardContent>95 </Card>96 );97}