Form
InputOTP
One-time-code input rendered as N single-character cells with paste distribution, autofill support and full keyboard navigation.
Import
import { InputOTP } from "@zephora/react";Examples
Basic
Six cells by default; paste a whole code into any cell.
<InputOTP onComplete={(code) => console.log(code)} />Length and mask
`length` controls the cell count; `mask` obscures entered characters.
<InputOTP length={4} mask />Controlled with completion
`onComplete` fires once the code reaches `length` characters.
Typed: —
const [code, setCode] = React.useState("");
const [done, setDone] = React.useState(false);
<InputOTP
value={code}
onValueChange={(next) => {
setCode(next);
setDone(false);
}}
onComplete={() => setDone(true)}
/>
{done && <p>Code complete!</p>}API
InputOTP props
| Prop | Type | Default | Description |
|---|---|---|---|
length | number | 6 | Number of characters in the code. |
value | string | — | Controlled code value. |
defaultValue | string | "" | Initial code value (uncontrolled). |
onValueChange | (value: string) => void | — | Called with the code on every edit. |
onComplete | (code: string) => void | — | Called once the code reaches length characters. |
mask | boolean | false | Obscures entered characters (renders password inputs). |
disabled | boolean | false | Disables every cell. |
invalid | boolean | false | Marks the code invalid: sets aria-invalid and error styling. |
unstyled | boolean | false | Headless mode — drops Zephora classes so your own CSS can style it. |
…rest | HTMLAttributes<HTMLDivElement> | — | Forwarded to the group wrapper element. |
Keyboard
| Key | Action |
|---|---|
0-9 / characters | Fills the cell and advances focus. |
Backspace | Clears the cell, or moves back and clears the previous one. |
Arrow Left / Arrow Right | Moves focus between cells. |
Home / End | Focuses the first / last cell. |
Paste | Distributes the pasted code across cells. |