StartFoundationsComponentsContent

OTP input

An OTP input takes a short one-time code, such as an SMS or email verification code, a two-factor code, or a PIN. It shows one box per character over a single real field.

Stable Figma
OverviewUsageAPIAccessibility
<tk-field label="Enter the 6-digit code we sent you" helper="Sent to +1 ••• ••• 4321">
  <tk-otp-input name="code"></tk-otp-input>
</tk-field>

Anatomy

Part What it is
tk-otp-input the element; one Tab stop
field part the row of boxes
box part one character box, 48×48px
input part the one real <input>, invisible, over the row

The label, help text, and error message come from a Field. Screen readers hear one field, not one per box.

Length, type, and mask

<tk-field label="Enter your 4-digit PIN">
  <tk-otp-input name="pin" length="4" mask></tk-otp-input>
</tk-field>
<tk-field label="Enter a backup code">
  <tk-otp-input name="backup" length="8" type="alphanumeric"></tk-otp-input>
</tk-field>
  • length sets the number of boxes: 6 by default, 4 for a PIN.
  • type: numeric (default) accepts 0–9 and shows the number pad; alphanumeric accepts letters and digits and keeps their case.
  • mask shows filled boxes as dots. Use it only for a code people know, such as a PIN: it can stop the phone from filling in an SMS code.

Typing and pasting

  • Typing fills a box and moves to the next. Typing on a filled box replaces it.
  • Backspace clears and steps back. Arrow keys, Home, and End move between boxes. Tab always leaves the field.
  • Pasting fills every box, from any position, and drops spaces and hyphens: "98 76-54" becomes 987654.
  • An SMS code from the phone's autofill fills every box at once.
  • The active box shows a blinking caret, or a steady one when reduced motion is on.

States

<tk-otp-input aria-label="Verification code" value="482913" readonly></tk-otp-input>
<tk-otp-input aria-label="Verification code" disabled></tk-otp-input>
<tk-field label="Enter the 6-digit code we sent you" error="That code is incorrect. Check it and try again.">
  <tk-otp-input name="code" value="123456"></tk-otp-input>
</tk-field>

The boxes don't change on hover. The active box takes the focus color and a thicker border; that is the focus indicator.

  • Error: set error on the Field. Every box turns red, the active one too, and the message shows under the row. The OTP input doesn't check the code; you decide when and what to say.
  • readonly: people can focus and copy the code, but not change it.
  • disabled: the field can't be focused or edited, and it's left out of the form.
  • Required: set required on the Field. The code must be complete to submit.
  • A correct code shows no green state. Move people on to the next screen.

Completion

When the last box fills, the field fires tk-complete with the code in detail.value. It doesn't submit or move focus by itself.

  • You can submit on tk-complete, but people using a screen reader or keyboard may want to check the code first. A verify button is safer.
  • If the code is wrong, set error on the Field and keep focus in the field.