OTP input

Takes a one-time code.

Sizes

  • Code

    sm

  • Code

    defaultdefault

  • Code

    lg

Length

  • Pairing code

    4

  • Code

    6default

States

  • Code

    empty

  • Code

    focus

  • Code

    filling

  • Code

    complete

  • Code

    invalid

  • Code

    disabled

Usage

When to use it
Use
A short code sent to the person or shown by an app: a sign-in code, a device pairing code.
Not for
A password or an API key. Use Input.
Not for
A quantity. Use Number input.

Rules

6 rules
Must
Set length to the code's exact length. Because onComplete fires when the last slot fills, so a slot too many never completes and one too few cuts the code.
Should
Verify in onComplete rather than behind a Continue button. Because a pasted or autofilled code is done the moment it lands, and a button adds a press for nothing.
Must
Name it with a Field and FieldLabel, or aria-label, saying where the code comes from. Because the slots are named only by their position, so nothing says which code goes in.
Must
On a wrong code, set aria-invalid and say why in a FieldError; keep the code in the slots. Because clearing the slots throws away what the person typed and leaves them guessing which digit was wrong.
Never
Build a code from separate Inputs, one per character. Because separate fields lose the paste of a whole code, the step back on Backspace and the phone's one-time-code autofill.
Never
Square off the slots with a radius class. Because each slot is a one-character field, and every one-line field in Glaze is a pill.

State order

5 states, highest first
1
disabled
2
invalid
3
focus
4
filled
5
empty

Accessibility

4 checks
The first slot carries the label; the others are named "Character 2 of 6" and so on.
A rejected character is announced ("Digits only") in a status region.
autocomplete="one-time-code" lets the phone offer a code from a message.
The slots read left to right in every language, since a code is not words.

Keyboard

4 keys
A character
Fills the slot and moves to the next.
Backspace
Clears the slot, or the one before an empty slot.
Left, Right
Move between slots.
Paste
Fills every slot from a whole code.

Edge cases

3 edge cases
Pasted code with spaces or a dash
The characters that fit the type fill in order.
Narrow screen
Six 32px slots and the dash need 232px; use size="sm" below that.
Wrong code
The slots keep it, turn coral, and the FieldError says why.

API

7 props
length
number
value, defaultValue, onValueChange
string default ''
onComplete
(code) => void
groups
number[] default halves for 6 or 8
validationType
'numeric' | 'alpha' | 'alphanumeric' | 'none' default 'numeric'
size
'sm' | 'default' | 'lg' default 'default'
aria-invalid
boolean

Tokens

15 tokens
--paper
#ffffff
--field
#efefef
--line-control
rgb(5 5 5 / 0.15)
--line-focus
rgb(5 5 5 / 0.32)
--line-faint
rgb(5 5 5 / 0.06)
--line-strong
rgb(5 5 5 / 0.45)
--fail
#e35e49
--text-1
rgb(5 5 5 / 0.80)
--text-disabled
rgb(5 5 5 / 0.32)
--control-sm
26px
--control
32px
--control-lg
36px
--radius-pill
999px
--type-label
500 13px/1.35 var(--font-sans)
--dur-state
160ms

Install

For your coding agent

GitHub

Please star me pookie

141

A new design system every week

Leave your email before you copy the prompt.