InputOtp
Six boxes, zero friction.
About
One-time-code boxes, the MFA pattern. A character fills its box and moves to the next, Backspace on an empty box steps back, and a paste fills the rest. Digits only unless alphanumeric is set. Form-associated: it posts the joined code under its name. The boxes read left to right in either direction, as a number does.
Usage
Basic
The boxes form a group named by the label, and each one is labeled "Digit n". Box one carries autocomplete="one-time-code", so a phone can offer the SMS code, and a paste into any box fills the rest.
Alphanumeric
Letters keep the case they are typed in, and the boxes ask for a text keyboard rather than a numeric pad.
Sizes
md is the default, as on every text field. lg widens the boxes and the digit for a sign-in page; sm shrinks them for a compact dialog or a side panel.
Masked and states
masked renders password boxes. The error line replaces help and carries role="alert"; a disabled field posts nothing.
Read-only
readonly keeps the code readable and in the tab order, refuses typing, Backspace and paste, and still posts it.
In a form
The joined code posts under the host name. required holds the form while any box is empty, and Reset restores the code the field mounted with.
Events
suiInput fires on every edit with the code so far. suiChange waits for the commit, Enter or focus leaving the boxes, so a host that saves on it saves once. suiComplete fires when the last box fills, the moment to start the lookup. suiFocus and suiBlur mark focus entering and leaving the boxes, not a move between them.
Keyboard
| Key | Action |
|---|---|
| Any accepted character | Fills the box, replacing the character it held, and moves to the next one. |
| Any other character | Ignored: the box keeps what it held. |
| Backspace | Clears the box. On an empty box, clears the one before it and moves there. |
| ArrowLeft ArrowRight | Moves to the previous or the next box. The boxes read left to right in either direction, as a number does. |
| Home End | Moves to the first or the last box. |
| Enter | Commits the code, which is what suiChange reports. |
API
<sui-input-otp>
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
alphanumeric | alphanumeric | boolean | false | Accept letters as well as digits, for alphanumeric backup and recovery codes (PrimeVue's integerOnly={false}). Off by default: an SMS or authenticator code is digits, and the boxes ask the phone keyboard for a numeric pad accordingly. Letters keep the case they are typed in. |
disabled | disabled | boolean | false | Disables every box. |
error | error | stringstring | undefined | Error message; paints every box in the danger tone and sets aria-invalid. | |
help | help | stringstring | undefined | Help text under the boxes. Replaced by error when set. | |
invalid | invalid | boolean | false | Danger borders without a message. |
label | label | stringstring | undefined | Group label. Without one the group takes the host's aria-label or aria-labelledby as its name, and "One-time code" without either; a visible label wins over both. Each box stays "Digit n". | |
length | length | number | 6 | Number of boxes. |
masked | masked | boolean | false | Renders password boxes, for a PIN that should not be read over a shoulder. |
name | name | stringstring | undefined | Form control name. Reflected: form entry construction reads the content attribute, while all three framework bindings set properties, so an unreflected name posts nothing at all. | |
readOnly | readonly | boolean | false | Display only: the code can be read and copied but not edited; the boxes still post it. |
required | required | boolean | false | Marks the field required: shows the asterisk and sets valueMissing while any box is empty. |
size | size | "lg" | "md" | "sm" | 'md' | Box size: md 42 by 48 with an 18px digit (the default, as on every text field), sm 36 by 40 for a compact dialog, lg 48 by 56 with a 22px digit for a sign-in page. |
value | value | string | '' | The code typed so far. Mutable. |
Events
| Event | Detail | React | Vue | Description |
|---|---|---|---|---|
suiBlur | void | onSuiBlur | @sui-blur | Fires when focus leaves the boxes, after the suiChange an edit owes; no detail. Does not bubble. |
suiChange | string | onSuiChange | @sui-change | Fires on commit (Enter, or focus leaving the boxes after an edit); detail is the code. The split matches sui-input-text and sui-input-mask, so a host that saves on suiChange saves once, not once per character. |
suiComplete | string | onSuiComplete | @sui-complete | Fires when every box is filled; detail is the full code. |
suiFocus | void | onSuiFocus | @sui-focus | Fires when focus enters the boxes from outside them; no detail. A move from one box to the next fires nothing, so the boxes read as one field, the way suiChange treats them. Does not bubble. |
suiInput | string | onSuiInput | @sui-input | Fires on every edit; detail is the code typed so far. |
Methods
| Method | Signature | Description |
|---|---|---|
setFocus() | setFocus() => Promise<void> | Moves keyboard focus to the first empty box (or the last one when full). |
Theming
Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.
Color12
Typography1
Spacing and size4
Radius1
Motion2
Every name above is listed with its value and its role in Foundations.