Input OTP
A one-time code, a character to a cell: small slanted wells of Input's, each holding one tall leaning character.
Install
# once per project: where @zeroui items come frompnpm dlx shadcn@latest registry add @zeroui=https://zeroui.catforest.dev/r/{name}.jsonpnpm dlx shadcn@latest add @zeroui/input-otpExamples
Four characters, and six in two runs
Four characters, on the back of the crate.
import { Field, FieldDescription, FieldLabel } from "@/components/zero/field";import { InputOTP, InputOTPSeparator, InputOTPSlot,} from "@/components/zero/input-otp";export default function InputOTPCode() { return ( <div className="grid gap-8"> <Field> <FieldLabel>Gate code</FieldLabel> <InputOTP length={4} validationType="alphanumeric" /> <FieldDescription> Four characters, on the back of the crate. </FieldDescription> </Field> <InputOTP length={6} aria-label="Sign-off code"> <InputOTPSlot /> <InputOTPSlot aria-label="Character 2 of 6" /> <InputOTPSlot aria-label="Character 3 of 6" /> <InputOTPSeparator /> <InputOTPSlot aria-label="Character 4 of 6" /> <InputOTPSlot aria-label="Character 5 of 6" /> <InputOTPSlot aria-label="Character 6 of 6" /> </InputOTP> </div> );}Behaviour
Typing moves to the next cell, Backspace moves back, and pasting fills the row. The cell being typed in draws the selection frame; inside an invalid Field the cells outline in danger. Digits only by default; validationType takes letters too.
Without children, InputOTP draws length cells; with InputOTPSlot and InputOTPSeparator you can split them into runs.
Props
InputOTP
| Prop | Type | Default | Description |
|---|---|---|---|
| length | number | — | How many characters. |
| validationType | "numeric" | "alpha" | "alphanumeric" | "none" | "numeric" | What a cell accepts. |
| onValueComplete | (value) => void | — | Called when every cell is filled. |
Also takes every prop of Base UI's OTPField.Root.
InputOTPSlot, InputOTPSeparator
Also takes every prop of Base UI's OTPField.Input.