Input OTP

A one-time code made of grouped digit slots.

Overview

One native input holds the digits, so paste, arrows, and backspace stay with the browser. The slots are visual. Set name when the value should submit with a form. Use onComplete to react when every digit is filled.

Preview

Customize

Length
4
Invalid

Installation

Add the component with the CLI. It copies the files in and installs anything they depend on.

npx vinyaas add input-otp

Usage

import { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot } from "@/components/ui/input-otp"; export function Code() { return ( <InputOTP length={6} aria-label="Verification code"> <InputOTPGroup> <InputOTPSlot index={0} /> <InputOTPSlot index={1} /> <InputOTPSlot index={2} /> </InputOTPGroup> <InputOTPSeparator /> <InputOTPGroup> <InputOTPSlot index={3} /> <InputOTPSlot index={4} /> <InputOTPSlot index={5} /> </InputOTPGroup> </InputOTP> ); }

Examples

PIN

A shorter code uses the same slots with length 4.

Invalid

invalid marks the field and the slots.

Disabled

A disabled code cannot be edited.

In practice

Confirm a sign-in email with a six-digit code, Verify, Resend, and success or error copy.

Enter the 6-digit code sent to ada@analytical.engine.

API

Other attributes for the underlying element are passed through.

NameTypeDefaultDescription
lengthnumber—How many digits the field accepts. Defaults to 6.
valuestring—Controlled digits. Non-digits are ignored.
onChange(value: string) => void—Called with the cleaned digit string.
onComplete(value: string) => void—Called once when the value reaches length. Fires again after a digit is removed and the code is completed again. Does not fire while disabled.
invalidboolean—Sets aria-invalid and the destructive slot border.

Accessibility

  • The input is named with aria-label or a label and id.
  • Slots are hidden from assistive technology.
  • invalid sets aria-invalid.
  • Paste fills the digits from the clipboard.