InputOTP
input-otp分格输入验证码,自动跳格并支持整段粘贴
用法
基础用法
6 位数字验证码,自动跳格、退格回退、整段粘贴自动分配。
tsx
<InputOTP length={6} value={otp} onChange={setOtp} onComplete={verify} />分组分隔
groupGap 在中间插入横线,呈现 3-3 分组视觉。
tsx
<InputOTP length={6} groupGap value={otp} onChange={setOtp} />任意字符
type="text" 接受字母数字混合的兑换码/邀请码。
tsx
<InputOTP length={6} type="text" value={code} onChange={setCode} />无效态
invalid 标红边框,校验失败时提示重输。
tsx
<InputOTP length={4} invalid value={otp} onChange={setOtp} />何时用
短信/邮箱验证码、PIN、二次验证码这类「定长、分格、填满即提交」的输入用。不要用普通文本框拼正则——本组件内置分段跳格、退格回退、整段粘贴拆分与 onComplete。需要任意长度自由文本请用普通 Input/SecretField。
导入
ts
import { InputOTP } from "@hulianui/ui"Props
继承根节点(role="group" 的 div)原生属性:id / data-* / aria-* / onFocus / onBlur 都能直接传。
| 名称 | 类型 | 默认 | 说明 |
|---|---|---|---|
| length | number | 6 | 分段数量 |
| value | string | - | 受控值 |
| defaultValue | string | - | 非受控初始值 |
| type | "numeric" | "text" | "numeric" | 仅数字(默认)或任意字符 |
| disabled | boolean | - | 禁用 |
| invalid | boolean | false | 校验失败态 |
| groupGap | boolean | - | 中间插入横线分隔符(3-3 分组视觉,如 XXX-XXX) |
| name | string | - | 提交标识。额外渲染一个持有完整值的隐藏 input(槽位各持一位,同名会提交出 N 个字段) |
| className | string | - | 容器类名 |
| aria-label | string | - | 无障碍标签 |
Events
| 事件 | 类型 | 说明 |
|---|---|---|
| onChange | (value: string) => void | 值变化回调 |
| onComplete | (value: string) => void | 填满时回调 |
| onBlur | (e: FocusEvent<HTMLDivElement>) => void | 焦点离开整组时触发;槽位之间跳焦不算。接 RHF Controller 时把 field.onBlur 传这里 |
禁忌 / 坑
onComplete仅在填满最后一格瞬间触发一次,验证逻辑放这里;不要在onChange里判value.length === length重复触发。- 受控用
value须配onChange,否则格子无法输入。 - 接 react-hook-form 时值是整串而非原生 input,必须走
Controller,并且要把 `field.onBlur` 传进来——不传的话touchedFields永不更新,mode: "onBlur"/"onTouched"的表单会静默失效(点进点出不校验,只有提交才报错)。 onBlur是整组语义:槽位之间跳焦不触发。想拿逐格失焦请自己在槽位上做,不要指望这个回调。
相关
SecretField · Combobox · Listbox · Mentions · Rating · Upload
Playground
(输入验证码)
<InputOTP
length={6}
type="numeric"
value={otp}
onChange={setOtp}
onComplete={verify}
/>