Here is a code with the demo I just found on Codepen, that handles pasting OTP also.
See the Pen OTP Field by Puneet Sharma (@webdevpuneet) on CodePen.
HTML
<body>
<h1>Enter OTP</h1>
<div class="otp-field">
<input type="text" maxlength="1" />
<input type="text" maxlength="1" />
<input class="space" type="text" maxlength="1" />
<input type="text" maxlength="1" />
<input type="text" maxlength="1" />
<input type="text" maxlength="1" />
</div>
</body>
CSS
body {
margin: 0;
font-family: "Poppins", sans-serif;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
background: #282a36;
height: 100vh;
color: #fff;
}
.otp-field {
display: flex;
}
.otp-field input {
width: 24px;
font-size: 32px;
padding: 10px;
text-align: center;
border-radius: 5px;
margin: 2px;
border: 2px solid #55525c;
background: #21232d;
font-weight: bold;
color: #fff;
outline: none;
transition: all 0.1s;
}
.otp-field input:focus {
border: 2px solid #a527ff;
box-shadow: 0 0 2px 2px #a527ff6a;
}
.disabled {
opacity: 0.5;
}
.space {
margin-right: 1rem !important;
}
JavaScript
const inputs = document.querySelectorAll(".otp-field input");
inputs.forEach((input, index) => {
input.dataset.index = index;
input.addEventListener("keyup", handleOtp);
input.addEventListener("paste", handleOnPasteOtp);
});
function handleOtp(e) {
/**
* <input type="text" 👉 maxlength="1" />
* 👉 NOTE: On mobile devices `maxlength` property isn't supported,
* So we to write our own logic to make it work. 🙂
*/
const input = e.target;
let value = input.value;
let isValidInput = value.match(/[0-9a-z]/gi);
input.value = "";
input.value = isValidInput ? value[0] : "";
let fieldIndex = input.dataset.index;
if (fieldIndex < inputs.length - 1 && isValidInput) {
input.nextElementSibling.focus();
}
if (e.key === "Backspace" && fieldIndex > 0) {
input.previousElementSibling.focus();
}
if (fieldIndex == inputs.length - 1 && isValidInput) {
submit();
}
}
function handleOnPasteOtp(e) {
const data = e.clipboardData.getData("text");
const value = data.split("");
if (value.length === inputs.length) {
inputs.forEach((input, index) => (input.value = value[index]));
submit();
}
}
function submit() {
console.log("Submitting...");
// 👇 Entered OTP
let otp = "";
inputs.forEach((input) => {
otp += input.value;
input.disabled = true;
input.classList.add("disabled");
});
console.log(otp);
// 👉 Call API below
}