Capítulo 24 de 108

Input OTP

Core Idea

InputOTP is an accessible one-time-password/PIN input with copy-paste support, built on the input-otp library. Composed of slots grouped visually, with a controllable pattern (digits only, alphanumeric, etc.).

Key Concepts

  • InputOTP: root component; maxLength (required), value/onChange for controlled mode, defaultValue for uncontrolled, disabled, pattern for input restriction.
  • InputOTPGroup: visually clusters a set of InputOTPSlots (e.g. 3+3 split).
  • InputOTPSlot: individual character cell; takes index (required, position in the value) and accepts aria-invalid for error styling.
  • InputOTPSeparator: visual divider between InputOTPGroups (e.g. dash between two groups of 3).
  • pattern: regex controlling allowed characters, e.g. REGEXP_ONLY_DIGITS, REGEXP_ONLY_DIGITS_AND_CHARS (imported from input-otp).

Code Examples

<InputOTP maxLength={6} defaultValue="123456">
  <InputOTPGroup>
    <InputOTPSlot index={0} />
    <InputOTPSlot index={1} />
    <InputOTPSlot index={2} />
    <InputOTPSlot index={3} />
    <InputOTPSlot index={4} />
    <InputOTPSlot index={5} />
  </InputOTPGroup>
</InputOTP>
<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>
  • O que demonstra: agrupamento 3+3 com separador visual, padrão comum de código de verificação.
const [value, setValue] = React.useState("")

<InputOTP maxLength={6} value={value} onChange={(value) => setValue(value)}>
  <InputOTPGroup>
    <InputOTPSlot index={0} />
    {/* ... */}
  </InputOTPGroup>
</InputOTP>
  • O que demonstra: modo controlado via value/onChange.
import { REGEXP_ONLY_DIGITS } from "input-otp"

<InputOTP maxLength={4} pattern={REGEXP_ONLY_DIGITS}>
  <InputOTPGroup>
    <InputOTPSlot index={0} />
    <InputOTPSlot index={1} />
    <InputOTPSlot index={2} />
    <InputOTPSlot index={3} />
  </InputOTPGroup>
</InputOTP>
  • O que demonstra: PIN de 4 dígitos restrito a números via pattern={REGEXP_ONLY_DIGITS}.
<InputOTPSlot index={0} aria-invalid />
  • O que demonstra: estado de erro por slot via aria-invalid (não há prop invalid no root).

Composition

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

Anti-patterns

  • Forgetting pattern={REGEXP_ONLY_DIGITS} for numeric-only codes: without it, the input accepts any character by default.
  • Relying on this page's own API Reference for prop details: it explicitly defers to the upstream input-otp docs (https://input-otp.rodz.dev) rather than listing full props here.

Key Takeaways

  1. Manual install requires the input-otp npm dependency (unlike pure Base UI components).
  2. Validation/error state is per-slot (aria-invalid on each InputOTPSlot), not a single prop on the root.
  3. Grouping and separators are purely visual/structural, the underlying value is still one contiguous string across all slots regardless of grouping.
  4. Supports copy-paste out of the box (a core feature of the underlying input-otp library).

Connects To

  • components-field: pairs with Field/FieldLabel for labeled OTP inputs.
  • components-input: sibling text-entry component; InputOTP is the specialized multi-box variant.