Skip to content
Protocore Design Systemv1.6.9

/// Inputs

OTPInput

A row of single-character cells for one-time-code / verification entry, with auto-advance, paste distribution, and arrow navigation.

import { OTPInput } from "@protocore/pds";
View as Markdown

Basics

Six numeric cells. Typing auto-advances, onValueChange reports the concatenated string on every edit, and onComplete fires once when the last cell fills. Controllable via value / defaultValue.

Entered:

Alphanumeric & masked

Set type="alphanumeric" to accept letters and digits, and mask to obscure each character — the pattern for backup / recovery keys. length sizes the row.

Enter your 8-character recovery key

In a Field, with error

Wrap in a Field for a label, hint, and announced error. The error path here triggers once a full-but-wrong code is entered.

We texted a 6-digit code to •••• 4471.

When to use it

Use OTPInput for short, fixed-length codes a user transcribes from a text message, authenticator app, or email — 2FA codes, email confirmations, recovery keys. The segmented cells make length obvious and paste-friendly. For free-form numeric entry (quantities, amounts) use NumberInput; for ordinary text use Input.

Usage

Do

  • Give the group an `aria-label` describing the code (e.g. "Two-factor code").
  • Match `length` to the real code length so paste fills exactly.
  • Use `type="numeric"` for digit-only codes — it sets the numeric `inputMode` for mobile keypads.
  • Handle `onComplete` to auto-submit, but still allow editing before the request resolves.

Don't

  • Don't use OTPInput for variable-length secrets like passwords — use a masked Input.
  • Don't stack more cells than the code has; empty trailing cells can never complete.
  • Don't disable paste — users routinely paste codes from another app.
  • Don't rely on cell color alone to signal an error; pair with a Field error message.

Accessibility

KeysAction
0–9 / A–ZFill the focused cell and advance to the next.
BackspaceClear the focused cell, or step back and clear the previous one if empty.
DeleteClear the focused cell in place.
Arrow Left / RightMove between cells without changing values.
Home / EndJump to the first / last cell.
PasteDistribute the pasted characters across cells from the focused one.
  • The cells are wrapped in a `role="group"` labelled by `aria-label`; each cell carries a positional label ("Digit 1 of 6").
  • Focusing a cell selects its content so a keystroke replaces the character.
  • The first cell advertises `autoComplete="one-time-code"` so iOS / Android can offer the SMS code.

OTPInput props

PropTypeDefaultDescription
aria-labelstringVerification codeAccessible label for the cell group. Default `"Verification code"`.
classNamestring
defaultValuestringInitial value when uncontrolled.
disabledbooleanfalseDisable every cell.
lengthnumber6Number of character cells. Default `6`.
maskbooleanfalseObscure entered characters (renders each cell as a password box).
onComplete((value: string) => void)Fires once with the full string when every cell is filled.
onValueChange((value: string) => void)Fires with the full concatenated string whenever any cell changes.
styleCSSProperties
typeenumnumericAccepted character class: `"numeric"` (0–9, default) or `"alphanumeric"`.
valuestringControlled value. Pair with `onValueChange`.

Related

  • InputThe base single-line text control — a sunken field with optional leading and trailing adornment slots.
  • FieldForm-field wrapper: a caption label, the control, and hint or error messaging with ARIA wired for you.
  • NumberInputNumeric field with a mono tabular value and a hairline stepper column — clamps to min/max and steps with the arrow keys.