This content originally appeared on DEV Community and was authored by Ajay Kumar
This OTP input component is a bit different from the typical ones you see. Normally, OTP input fields consist of 6 separate input boxes for each digit, and handling each one can be a real hassle, especially when you need to manage the focus, cursor position, and backspacing between fields. But with this component, I’ve simplified it by using a single input field. This is more efficient and less cluttered, as you only need to manage one field, which reduces the complexity of the code.
Another cool feature of this component is that it automatically handles the OTP entry, and it also supports autocomplete for mobile out of the box. This means when users try to input OTP on their phone, it can automatically recognize and fill in the digits without much hassle. So no more worrying about manually typing in each digit or dealing with the inconvenience of focus shifting between inputs.
The OTP blocks themselves are visually clean with a nice blue background, and when the field is focused, it shows a ring effect, making it obvious where the user is typing. The component is fully responsive and works seamlessly across different screen sizes. It also handles keypresses like Backspace and Delete gracefully.
Tech Requirements:- React, Tailwind,Typescript
import React, { useState } from 'react';
interface OtpInputProps {
otpLength: number
onChange: Function
}
const OtpInput: React.FC<OtpInputProps> = ({ otpLength = 6, onChange }) => {
const [otp, setOtp] = useState('');
const [focused, setFocused] = useState<boolean>(false);
const handleChange = (event: any) => {
const value = event.target.value;
if (/^\d*$/.test(value) && value.length <= otpLength) {
setOtp(value);
onChange(value);
}
};
const handleKeyDown = (event: any) => {
if (event.key === 'Backspace' || event.key === 'Delete') {
event.preventDefault();
setOtp((prevOtp) => prevOtp.slice(0, -1));
}
else if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
event.preventDefault();
}
};
return (
<div className="relative flex gap-2 w-fit">
{Array.from({ length: otpLength }).map((_, index) => (
<div
key={index}
className={`w-[45px] h-[50px] bg-blue-500 rounded-md flex items-center border-2 border-white justify-center text-white text-2xl
${otp[index] ? '' : 'opacity-80'}
${otp[index] === undefined ? '' : ''}
${focused && (index === otp.length || (otpLength === otp.length && index === otpLength - 1)) ? 'ring-2 ring-primary' : 'ring-2 ring-transparent'} // Active block ring
`}
>
{otp[index] || '-'}
</div>
))}
{/* Transparent input field */}
<input
type="text"
inputMode="numeric"
maxLength={otpLength}
pattern="\d{6}"
autoComplete="one-time-code"
autoFocus={true}
className="absolute top-0 left-0 w-full h-full bg-transparent caret-transparent text-transparent focus:outline-none ltr:text-left rtl:text-right
selection:bg-transparent selection:text-transparent"
value={otp}
onChange={handleChange}
onKeyDown={handleKeyDown}
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
/>
</div>
);
};
export default OtpInput;
This content originally appeared on DEV Community and was authored by Ajay Kumar

Ajay Kumar | Sciencx (2025-01-11T07:51:25+00:00) Opt input react component. Retrieved from https://www.scien.cx/2025/01/11/opt-input-react-component/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.