use UI

OTP Input

Also called one-time code, verification code, PIN input, 2FA code

A field for a short code, presented as one box per character.

Example

Verification code

Six digits, sent by text message. Paste works from any box.

0 of 6 entered — nothing is submitted until you press Verify.

The value behind the boxes

······

The first box carries autocomplete="one-time-code", which is what lets a phone offer the code straight from the message. Every box is labelled in sequence, so a screen reader announces “Digit 3 of 6” rather than a third anonymous text field.

When to use it

  • A short fixed-length code is copied from somewhere else — SMS, an authenticator, an email.
  • Reading the code back character by character helps, because the user is comparing it to another screen.
  • The length is known and small: four to eight characters. Beyond that the boxes stop helping.

When not to

  • The value is remembered rather than copied. A password or a passphrase belongs in one field.
  • The length varies. Boxes promise an exact count, and a code that might be six or eight characters breaks that promise.
  • The code is alphanumeric and case-sensitive. Separate boxes make it harder to see the whole string and check it.

Trade-offs

  • Progress is visible at a glance — four of six filled is obvious without counting.
  • Character-by-character comparison against the source is easier than scanning one long string.
  • Mistakes are localised: one wrong character is one box to fix.
  • Every convenience has to be rebuilt by hand: paste, autofill, Backspace, arrow keys, selection.
  • Screen reader output is fragmented — six fields announced separately rather than one code.
  • Mobile keyboards may reopen between boxes, and the OS autofill suggestion sometimes only targets the first field.

Accessibility

What this pattern needs in order to work for everyone.

Keyboard
  • Paste must fill the whole code from any box, not drop six characters into one. Handle it on paste, spread the characters, and move focus to the end.
  • Backspace on an empty box moves to the previous one and clears it. Without that, correcting a typo means clicking.
  • Arrow keys move between boxes; typing a character advances automatically, but only forwards — do not steal focus while someone is reviewing.
Roles and state
  • Give the group a name with `<fieldset>` and `<legend>`, or `role="group"` and a label, so “Verification code” is announced before the first box.
  • Label each box in sequence — “Digit 1 of 6” — otherwise a screen reader reads six anonymous text fields.
  • Set `autocomplete="one-time-code"` and `inputmode="numeric"`. The first unlocks OS-level autofill from SMS; the second brings up the number pad.
  • Announce the result, not just the boxes: a polite live region saying “Code complete, verifying” beats silence after the sixth character.
Focus
Focus advances on entry and retreats on Backspace, and stays put when the code is complete — jumping straight to a Verify button robs the user of a last look.

In the wild

  • Stripe verification Six boxes with working paste and SMS autofill, and a visible Verify button rather than auto-submit.
  • GitHub 2FA Accepts a pasted code and submits on completion, with the field still editable afterwards.