← Components/Inputs & Forms

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 [suggest
TagInput
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 [minVal
RangeSlider
Inputs & Forms