OTPInput
otpinput-1779378412632.tsx
'use client'
import { useRef, useState, KeyboardEvent, ClipboardEvent } from 'react'
const LENGTH = 6
export default function OTPInput() {
const [values, setValues] = useState<string[]>(Array(LENGTH).fill(''))
const [verified, setVerified] = useState<boolean | null>(null)
const [loading, setLoading] = useState(false)
const inputs = useRef<(HTMLInputElement | null)[]>([])
function handleChange(i: number, val: string) {
if (!/^[0-9]?$/.test(val)) return
const next = [...values]
next[i] = val
setValues(next)
if (val && i < LENGTH - 1) inputs.current[i + 1]?.focus()
setVerified(null)
}
function handleKey(i: number, e: KeyboardEvent<HTMLInputElement>) {
if (e.key === 'Backspace' && !values[i] && i > 0) {
inputs.current[i - 1]?.focus()
}
}
function handlePaste(e: ClipboardEvent) {
e.preventDefault()
const text = e.clipboardData.getData('text').replace(/D/g, '').slice(0, LENGTH)
const next = [...values]
for (let i = 0; i < text.length; i++) next[i] = text[i]
setValues(next)
inputs.current[Math.min(text.length, LENGTH - 1)]?.focus()
}
async function verify() {
const code = values.join('')
if (code.length < LENGTH) return
setLoading(true)
await new Promise(r => setTimeout(r, 1200))
setVerified(code === '123456')
setLoading(false)
}
const complete = values.every(v => v !== '')
return (
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 24, padding: 48, background: '#0A0A0A' }}>
<div style={{ textAlign: 'center' }}>
<div style={{ color: '#F5F5F0', fontWeight: 700, fontSize: 20, marginBottom: 6 }}>Enter verification code</div>
<div style={{ color: '#666', fontSize: 14 }}>Sent to your email · Use <strong style={{ color: '#C9A84C' }}>123456</strong> to test</div>
</div>
<div style={{ display: 'flex', gap: 10 }} onPaste={handlePaste}>
{values.map((v, i) => (
<input key={i}
ref={el => { inputs.current[i] = el }}
value={v} maxLength={1} inputMode="numeric"
onChange={e => handleChange(i, e.target.value)}
onKeyDown={e => handleKey(i, e)}
autoFocus={i === 0}
style={{
width: 48, height: 56, textAlign: 'center', fontSize: 22, fontWeight: 700,
background: '#111', border: `2px solid ${
verified === null ? (v ? 'rgba(201,168,76,0.5)' : 'rgba(255,255,255,0.1)') :
verified ? 'rgba(34,197,94,0.5)' : 'rgba(239,68,68,0.5)'
}`,
borderRadius: 10, color: '#F5F5F0', outline: 'none',
transition: 'border-color 0.2s',
}}
/>
))}
</div>
<button onClick={verify} disabled={!complete || loading}
style={{
background: complete ? '#C9A84C' : 'rgba(255,255,255,0.06)',
color: complete ? '#0A0A0A' : '#555',
border: 'none', padding: '13px 36px', borderRadius: 10,
cursor: complete ? 'pointer' : 'not-allowed',
fontWeight: 700, fontSize: 15, transition: 'all 0.2s',
}}
>{loading ? '⏳ Verifying...' : verified === true ? '✓ Verified!' : verified === false ? '✗ Invalid code' : 'Verify code'}</button>
</div>
)
}Component info
CategoryInputs & Forms
Frameworkreact
TierFREE
Views0
Copies0
About
One-time password input with auto-focus, paste support, and animated verification
More from Inputs & Forms
'use client';
import { useState, useEffect } from 'react';
interface Tag {
id: number;
name: string;
}
const TagInput = () => {
const [tags, setTags] = useState<Tag[]>([]);
const [inputValue, setInputValue] = useState('');
const [suggestTagInput
Inputs & Forms
'use client';
import React, { useState } from 'react';
interface File {
name: string;
size: number;
progress: number;
}
const FileUpload = () => {
const [dragOver, setDragOver] = useState(false);
const [files, setFiles] = useState<File[]FileUpload
Inputs & Forms
import React, { useState } from 'react';
const OTPInput = () => {
const [otp, setOtp] = useState(new Array(6).fill(''));
const [activeIndex, setActiveIndex] = useState(0);
const handleChange = (e, index) => {
const value = e.target.value;OTPInput
Inputs & Forms
'use client';
import React, { useState } from 'react';
interface RangeSliderProps {
min: number;
max: number;
defaultValue: [number, number];
}
const RangeSlider: React.FC<RangeSliderProps> = ({ min, max, defaultValue }) => {
const [minValRangeSlider
Inputs & Forms