Yugen UI

InputOTP

InputOTP collects a one-time passcode, one character per box.

Typing moves to the next box, Backspace goes back to the previous one, pasting (Ctrl+V) fills in the whole code, and onComplete runs once every box is filled. The boxes share Input's styling; the first one has autocomplete="one-time-code" so the browser can fill in a code received by SMS.

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.

TSX
// 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.

Enter all 6 digits

onComplete

Called when all 6 digits are entered.

Letters and digits

pattern="alphanumeric", length={4}.

That code is incorrect. Try again.

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

Do
  • 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
  • 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 · TypeDefaultDescription
lengthnumberDefault: 6Number of boxes.
value / defaultValuestringDefault: —Current code.
onValueChange(value: string) => voidDefault: —Called whenever the code changes.
onComplete(code: string) => voidDefault: —Called when length characters have been entered.
pattern"digits" | "alphanumeric" | RegExpDefault: "digits"Allowed characters.
groups / separatornumber[] / ReactNodeDefault: —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 · TypeDefault (English)messagesVi
slot(position: number, length: number) => string

aria-label của từng ô; position đếm từ 1.

Default (English)(position, length) => `Character ${position} of ${length}`messagesVi(position, length) => `Ký tự ${position} trên ${length}`