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
lengthnumbervalue, defaultValue, onValueChangestringdefault''onComplete(code) => voidgroupsnumber[]defaulthalves for 6 or 8validationType'numeric' | 'alpha' | 'alphanumeric' | 'none'default'numeric'size'sm' | 'default' | 'lg'default'default'aria-invalidboolean
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