Input OTP
InputOTP collects a one-time passcode, one character per box.
Import
Install from npm, copy the source into your project with @yugen-ui/cli or the shadcn CLI, or import directly when working in this repo.
// npm install yugen-uiimport { InputOTP } from "yugen-ui";Variants
Each tile is a standalone example: hover to copy, or press Code to see the source.
onComplete
Called when all 6 digits are entered.
Letters and digits
pattern="alphanumeric", length={4}.
In a Field, with an error
Field links the label to the first box and passes aria-invalid to every box.
Size & disabled
small (32px) and disabled. medium (40px) is the default; large (48px) is in the Letters and digits example.
Usage
- Say where the code was sent (“Code sent to 09xx xxx 678”).
- Verify automatically through onComplete once the code is complete, instead of making people press a button.
- Split long codes into groups (groups) so they are easier to read and check.
- Don't use InputOTP for passwords or long data. Use Input.
- Don't clear the whole code when one character is wrong; let people fix individual boxes.
Props
| Prop · Type | Default | Description |
|---|---|---|
| lengthnumber | Default: 6 | Number of boxes. |
| value / defaultValuestring | Default: — | Current code. |
| onValueChange(value: string) => void | Default: — | Called whenever the code changes. |
| onComplete(code: string) => void | Default: — | Called when length characters have been entered. |
| pattern"digits" | "alphanumeric" | RegExp | Default: "digits" | Allowed characters. |
| groups / separatornumber[] / ReactNode | Default: — | Box groups and the element between them. |
| size"small" | "medium" | "large" | Default: "medium" | Box size 32 / 40 / 48px. |
| disabled, name, autoFocus— | Default: — | name adds a hidden input that holds the code when the form is submitted. |
Messages
Text built into the component: labels, aria-labels, screen reader announcements.
English by default. Change it with the messages prop of YugenProvider, by the namespace below; messagesVi has the Vietnamese set. See Interface language.
messages.inputOTP
| Key · Type | Default (English) | messagesVi |
|---|---|---|
| slot(position: number, length: number) => string aria-label của từng ô; | Default (English)(position, length) => `Character ${position} of ${length}` | messagesVi(position, length) => `Ký tự ${position} trên ${length}` |