Input OTP

Accessible one-time password input with copy-paste. Slots are size-8 to match the control scale. Built on the input-otp package.

Basic

Six slots with InputOTPSeparator between groups. Supports paste.

Installation

CLI
npx @sonojs/ui@latest add input-otp
Also needsnpm i input-otp lucide-react

Composition

structure
InputOTP
├── InputOTPGroup
│   ├── InputOTPSlot
│   └── …
├── InputOTPSeparator
└── InputOTPGroup
    └── …

Usage

input-otp.tsx
import {
  InputOTP,
  InputOTPGroup,
  InputOTPSeparator,
  InputOTPSlot,
} from "@/components/ui/input-otp"

export function Example() {
  return (
    <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>
  )
}

Props

PropTypeDefaultDescription
maxLengthnumber—Required. Number of characters / slots.
patternstring—Regexp string — e.g. `REGEXP_ONLY_DIGITS` from `input-otp`.
value / onChangestring / (value) => void—Controlled value API.
disabledbooleanfalseDisables the underlying input.
indexnumber—Required on `InputOTPSlot` — zero-based slot index.
containerClassNamestring—Classes for the OTP container flex row.