WebberUI

OTP Input

驗證碼分格輸入:單一隱形 input 蓋在視覺格子上,支援貼上、錯誤抖動、成功波紋泛綠。

載入預覽⋯

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

6
<OtpInput />

安裝

npx shadcn@latest add https://webberui.com/r/otp-input.json

安裝時會一併寫入 --wb-duration-fast--wb-ease-out CSS 變數到你的全域樣式。

安裝依賴後,從 registry JSON(/r/otp-input.jsonfiles[0].content)複製 otp-input.tsx 原始碼到你的 components/ui/ 目錄,並在全域 CSS 加入:

npm install motion clsx tailwind-merge
:root {
  --wb-duration-fast: 200ms;
  --wb-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

使用

import { OTPInput } from "@/components/ui/otp-input";

<OTPInput
  onComplete={(code) => verify(code)}
  error={isError}
  success={isSuccess}
/>

不傳 value 時由元件內部管理;需要在驗證失敗後清空重來時,改用受控模式(value + onChange)。

Props

Prop型別預設值說明
lengthnumber6格數
valuestring受控值;不傳則由元件內部管理
onChange(value: string) => void值變更時觸發
onComplete(code: string) => void輸入滿 length 位時觸發,回傳完整驗證碼
errorbooleanfalse錯誤狀態:整排 x 軸抖動、邊框轉紅
successbooleanfalse成功狀態:格子依序波紋泛綠
type'numeric' | 'alphanumeric''numeric'允許的字元類型;alphanumeric 會自動轉大寫
disabledbooleanfalse停用輸入

可及性

採「單一隱形 input + 視覺格子」模式,而非 N 個獨立 input:

  • 螢幕閱讀器只會看到一個標準文字欄位(aria-label="驗證碼"),不用在六個欄位間跳轉;視覺格子皆為 aria-hidden
  • autocomplete="one-time-code":iOS/Android 收到簡訊驗證碼時可一鍵自動填入
  • 貼上完整驗證碼直接生效,無需逐格分配
  • 鍵盤行為完全是原生 input:Backspace 刪除、inputMode="numeric" 在行動裝置叫出數字鍵盤
  • error 時設定 aria-invalid,輔助技術可得知欄位狀態

細節

  • 當前格顯示呼吸明滅的 caret 與 focus ring,字元以 scale 0.5 → 1 pop 進格
  • 成功波紋以每格 60ms 的 stagger 依序將邊框與文字轉綠
  • 使用者系統開啟「減少動態效果」時,停用抖動與 pop 動畫,字元與狀態直接顯示

On this page