OTPInput
otpinput-1779394025958.tsx
'use client'
import { useState, useRef } from 'react'
export default function OTPInput({ length = 6, onComplete }) {
const [values, setValues] = useState(Array(length).fill(''))
const refs = Array.from({ length }, () => useRef(null))
const handleChange = (i, e) => {
const val = e.target.value.replace(/[^0-9]/g, '').slice(-1)
const next = [...values]; next[i] = val; setValues(next)
if (val && i < length - 1) refs[i+1].current?.focus()
if (next.every(v => v) && next.join('').length === length) onComplete?.(next.join(''))
}
const handleKey = (i, e) => {
if (e.key === 'Backspace' && !values[i] && i > 0) refs[i-1].current?.focus()
}
const handlePaste = (e) => {
const pasted = e.clipboardData.getData('text').replace(/[^0-9]/g, '').slice(0, length)
const next = [...values]
pasted.split('').forEach((c, i) => { next[i] = c })
setValues(next)
refs[Math.min(pasted.length, length-1)].current?.focus()
}
return (
<div style={{ display:'flex', flexDirection:'column', gap:'16px', alignItems:'center' }}>
<div style={{ display:'flex', gap:'10px' }}>
{values.map((v, i) => (
<input
key={i} ref={refs[i]} value={v} maxLength={1}
onChange={e => handleChange(i, e)} onKeyDown={e => handleKey(i, e)} onPaste={handlePaste}
style={{
width:'48px', height:'56px', textAlign:'center', fontSize:'22px', fontWeight:700,
border:'2px solid ' + (v ? '#6d28d9' : '#e2e8f0'),
borderRadius:'12px', outline:'none', color:'#1e293b',
background:v ? '#f5f3ff' : '#fff', transition:'all 0.15s',
}}
/>
))}
</div>
{values.every(v => v) && (
<div style={{ color:'#10b981', fontWeight:600, fontSize:'14px' }}>✓ Code entered: {values.join('')}</div>
)}
</div>
)
}Component info
CategoryInputs & Forms
Frameworkreact
TierFREE
Views0
Copies0
About
OTP/verification code input with auto-focus and paste support
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