Basel Standard

Basel Standard / Docs

Input OTP

Multi-slot verification input for short codes that need explicit position, focus, and scan order.

Use the grouped slots when a short verification code needs clear position and keyboard focus.

InputOTP turns a short verification code into a grouped sequence of slots without losing the single-input interaction model. It works well when the user should understand code length, current position, and completion state at a glance.

Installation

Install
Purchase access, then open /account/install to issue a registry token.

Usage

import { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot } from "@/components/ui/input-otp"
<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>

Why This Primitive Exists

A verification code should be easy to scan and hard to misread. The slot layout makes the expected length explicit while the underlying input model still handles typing, paste, and keyboard movement as one control.

  • Use it for short one-time codes, confirmation steps, or secure handoff gates.
  • Use separators when the code benefits from chunking, such as 123-456.
  • Avoid it for ordinary numeric entry, passwords, or identifiers that should behave like a normal text field.

Examples

Basic Six-Digit Entry

The default grouped layout is enough for most verification steps.

Use the grouped slots when a short verification code needs clear position and keyboard focus.

<InputOTP maxLength={6}>
  <InputOTPGroup>
    <InputOTPSlot index={0} />
    <InputOTPSlot index={1} />
    <InputOTPSlot index={2} />
    <InputOTPSlot index={3} />
    <InputOTPSlot index={4} />
    <InputOTPSlot index={5} />
  </InputOTPGroup>
</InputOTP>

Chunked With A Separator

Split the code visually when the user will scan or read it in grouped segments.

1
2

Separators help a longer code scan as two chunks without breaking the single input model.

<InputOTP maxLength={6}>
  <InputOTPGroup>{/* first 3 slots */}</InputOTPGroup>
  <InputOTPSeparator />
  <InputOTPGroup>{/* last 3 slots */}</InputOTPGroup>
</InputOTP>

In Context

Keep the code input next to the explanation and recovery actions so the interruption still feels local to the workflow.

Verification step

Keep OTP entry close to the message that explains why the interruption exists.

We sent a six-digit approval code to the archive owner before release access can be restored.

Current value: Waiting for code

<CardContent>
  <p>We sent a six-digit approval code to the archive owner.</p>
  <InputOTP maxLength={6}>{/* grouped slots */}</InputOTP>
</CardContent>

Guidance

Use OTP Only For Short Codes

  • Keep lengths short and explicit.
  • Use a normal input when the value is longer, editable, or not time-sensitive.
  • Pair the control with nearby copy that says where the code was sent and why it is required.

Preserve The Single-Input Model

  • Treat the slots as one field, not six independent inputs.
  • Let paste fill the full sequence when the underlying library supports it.
  • Avoid inserting extra logic per slot unless the interaction genuinely requires it.

Keep Recovery Actions Nearby

  • Provide resend or alternate verification actions close to the input.
  • Explain expiry, delivery delay, or fallback paths in short supporting copy.
  • If the code step belongs to a larger confirmation surface, keep it inside that card or modal rather than on a disconnected page.

API Reference

Exports

ExportRendersNotes
InputOTPOTPInputRoot input wrapper that manages the code value and slot context.
InputOTPGroupdivGroups a run of adjacent slots.
InputOTPSlotdivIndividual rendered slot; requires an index.
InputOTPSeparatordivVisual divider between slot groups.

InputOTP

InputOTP forwards the underlying OTPInput props, including controlled and uncontrolled value handling.

PropTypeNotes
maxLengthnumberRequired for most compositions so the slot count matches the expected code length.
valuestringControlled current value.
onChange(value: string) => voidFired whenever the code changes.
containerClassNamestringExtends the outer flex wrapper around the slot groups.
classNamestringExtends the underlying hidden input element.

InputOTPSlot

PropTypeNotes
indexnumberRequired slot index into the current OTP context.
classNamestringExtends the slot styling for custom width or emphasis.

InputOTPGroup and InputOTPSeparator also forward their native div props directly.