v0.5.1

Verification Code Input

Segmented input for entering verification or OTP codes.

Installation

npx paubha@latest add verification-code-input

Usage

import { VerificationCodeInput } from "@/components/ui/verification-code-input";

<VerificationCodeInput aria-label="6-digit verification code" />

Examples

Custom length

Error

Invalid verification code. Please try again.

Disabled

API reference

PropTypeDefaultDescription
lengthnumber6Number of digit cells.
defaultValuestring—Uncontrolled initial code.
valuestring—Controlled code, pair with onValueChange.
onValueChange(value: string) => void—Called with the accumulated code on every change.
errorbooleanfalseShows every cell in the error color and marks them aria-invalid.
errorMessageReact.ReactNode—Shown below the cells while error is set; linked via aria-describedby.
disabledbooleanfalseDisables every cell.
aria-labelstring—Required. Describes the whole group, e.g. "6-digit verification code".

Accessibility

Accessibility

  • Group. Wrapped in role="group" with a required aria-label describing the whole code.

  • Cells. Each digit is its own input, labeled aria-label="Digit N of M".

  • Auto-advance. Typing a digit moves focus to the next cell. Backspace on an empty cell moves focus back to the previous one.

  • Paste. Pasting a full code fills every cell at once.

  • Error. Announced via aria-invalid on every cell.

  • Focus ring. Visible on Tab via shadow-glow-focus.

When to use

Use for one-time passcodes (OTP): SMS verification, 2FA, email confirmation. Each digit gets its own cell for clarity.

Do:

  • Auto-focus the first cell
  • Auto-advance on input
  • Allow pasting the full code
  • Support backspace to the previous cell

Don't:

  • Use for regular text entry
  • Hide the digits, these are temporary, not sensitive like a password
  • Make the cells too small on mobile
  • Input: for standard text entry
  • Field: wraps this with a label and helper text
  • Button: for submitting after code entry