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.json 的 files[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 | 型別 | 預設值 | 說明 |
|---|---|---|---|
length | number | 6 | 格數 |
value | string | — | 受控值;不傳則由元件內部管理 |
onChange | (value: string) => void | — | 值變更時觸發 |
onComplete | (code: string) => void | — | 輸入滿 length 位時觸發,回傳完整驗證碼 |
error | boolean | false | 錯誤狀態:整排 x 軸抖動、邊框轉紅 |
success | boolean | false | 成功狀態:格子依序波紋泛綠 |
type | 'numeric' | 'alphanumeric' | 'numeric' | 允許的字元類型;alphanumeric 會自動轉大寫 |
disabled | boolean | false | 停用輸入 |
可及性
採「單一隱形 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 動畫,字元與狀態直接顯示