Skip to content

Digit Entry Views

InputOTP is the digit-entry control for one-time codes, PINs, and other short fixed-length numeric or alphanumeric values. Each character lands in its own cell, with optional separators between groups, so a six-digit verification code reads as two clean groups of three. It is built on the input-otp library and composed from slotted parts you arrange yourself.

Live demo

The interactive story below runs from the deployed Storybook.

Usage

Source: input-otp.tsx

import {
InputOTP,
InputOTPGroup,
InputOTPSlot,
InputOTPSeparator,
} from "@beacon/design-system";
// Six-digit code split into two groups of three.
<InputOTP maxLength={6}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>

Parts

PartRole
InputOTPThe root control. Set maxLength to the number of characters; accepts the props of the underlying OTPInput (including value, onChange, disabled, and containerClassName).
InputOTPGroupWraps a run of slots so adjacent cells share rounded ends and borders.
InputOTPSlotA single character cell. Requires an index prop matching its position; shows the active ring and caret automatically.
InputOTPSeparatorA visual divider (a dot) placed between groups.

When to use

  • One-time passcodes and SMS or email verification codes.
  • Short fixed-length PINs or access codes where per-digit cells aid readability.

Do not use InputOTP for general numeric entry such as amounts or quantities; use a plain Input with type="number" instead. Always pass each InputOTPSlot an index that matches its position and keep maxLength in sync with the number of slots.