8pt

OTP Input

验证码输入•输入
介绍

六格验证码:输入自动跳格、退格回退、整段粘贴自动分配。填满后校验,错误抖动,正确变绿。

纯 HTML、CSS 与少量原生 JS,没有框架依赖。复制提示词交给 Claude Code、Cursor、Trae 或 Codex,模型会把 OTP Input 加进你的项目并换成你的配色。

适用场景

搜索框、AI 对话输入框、表单字段、文件上传和验证码等用户输入的地方。

安装

订阅 Builder 后,用 8pt CLI 装进项目,或在已接入 8pt MCP 的编辑器里直接调用。

$ npm i -g @8pt-dev/cli && 8pt add otp-input
mcp › 使用 8pt MCP 调用 get_component("otp-input")

代码

OTP Input 的源码,动效只用 transform 与 opacity,并尊重减少动态效果设置。

<form class="x-otp" autocomplete="one-time-code">
  <b>输入验证码</b>
  <small>已发送到 a•••@example.com · 示例码 246810</small>
  <div class="x-otp__row">
    <input inputmode="numeric" maxlength="1" aria-label="第 1 位"><input inputmode="numeric" maxlength="1" aria-label="第 2 位"><input inputmode="numeric" maxlength="1" aria-label="第 3 位"><span aria-hidden="true">–</span><input inputmode="numeric" maxlength="1" aria-label="第 4 位"><input inputmode="numeric" maxlength="1" aria-label="第 5 位"><input inputmode="numeric" maxlength="1" aria-label="第 6 位">
  </div>
  <p class="x-otp__msg" aria-live="polite"></p>
</form>
.x-otp{display:grid;justify-items:center;gap:8px;color:var(--d-fg,#fff);text-align:center}
.x-otp b{font:650 16px/1.2 var(--d-font,system-ui,sans-serif)}
.x-otp small{font:12px/1.3 var(--d-font,system-ui,sans-serif);color:var(--d-muted,#9b9ba8)}
.x-otp__row{display:flex;align-items:center;gap:6px;margin-top:8px}
.x-otp__row span{color:var(--d-muted,#9b9ba8)}
.x-otp input{width:38px;height:46px;padding:0;border-radius:10px;border:1.5px solid var(--d-line,rgba(255,255,255,.16));background:var(--d-card,#14141c);color:inherit;font:700 20px/1 ui-monospace,monospace;text-align:center;outline:0;caret-color:var(--d-accent,#4D74FF);transition:border-color .2s,transform .2s}
.x-otp input:focus{border-color:var(--d-accent,#4D74FF);transform:translateY(-2px)}
.x-otp input.fill{border-color:color-mix(in srgb,var(--d-fg,#fff) 40%,transparent)}
.x-otp.ok input{border-color:#3dd68c;color:#3dd68c}
.x-otp.bad .x-otp__row{animation:x-otp-shake .4s}
.x-otp.bad input{border-color:#ff6b6b}
@keyframes x-otp-shake{20%,60%{transform:translateX(-6px)}40%,80%{transform:translateX(6px)}}
…
const init = (root) => {
  const form = root.querySelector('.x-otp'), ins = [...form.querySelectorAll('input')], msg = form.querySelector('.x-otp__msg');
  const CODE = '246810';
  let t;
  const check = () => { const v = ins.map(i => i.value).join(''); form.classList.remove('ok', 'bad');
    if (v.length < 6) { msg.textContent = ''; return; }
    void form.offsetWidth;
    if (v === CODE) { form.classList.add('ok'); msg.textContent = '✓ 验证成功'; }
    else { form.classList.add('bad'); msg.textContent = '验证码不正确'; clearTimeout(t); t = setTimeout(() => { ins.forEach(i => { i.value = ''; i.classList.remove('fill'); }); form.classList.remove('bad'); msg.textContent = ''; ins[0].focus(); }, 900); } };
  ins.forEach((inp, i) => {
    inp.addEventListener('input', () => { inp.value = inp.value.replace(/\D/g, '').slice(-1); inp.classList.toggle('fill', !!inp.value); if (inp.value && ins[i + 1]) ins[i + 1].focus(); check(); });
    inp.addEventListener('keydown', e => { if (e.key === 'Backspace' && !inp.value && ins[i - 1]) { ins[i - 1].focus(); ins[i - 1].value = ''; ins[i - 1].classList.remove('fill'); check(); }
…
订阅 Builder 查看完整源码。查看价格

更多输入组件

查看全部

AI Prompt Composer

AI Prompt Input

Glowing Search Bar

Command Palette

File Dropzone

Date Range Pill

更多组件

查看全部

Film Strip Carousel

Auto Tab Showcase

Media Bento Grid

Agent Chat Window

Model Pill Marquee

Director Art Cards

Mac File Window

Disk Cleanup Panel

继续探索