Input OTP

Accessible fixed-length code entry — each character gets its own cell, with copy/paste and caret tracking handled for you. Reach for it when the value is a short, known-length token: a 2FA/OTP code, an email verification PIN, or an invite key. For free-length or formatted text (phone, card number, anything the user can't predict the length of) use Input instead. Pair InputOTPGroup + InputOTPSeparator to chunk longer codes (e.g. 3-3) for readability. Slots sit at the canonical md control size (32px) so they line up with md Input and Button in a form.

Default (6-digit)

"use client";

import * as React from "react";
import { InputOTP, InputOTPGroup, InputOTPSlot } from "@liquidai/react";

export function Example() {
  const [value, setValue] = React.useState("");
  return (
    <InputOTP maxLength={6} value={value} onChange={setValue}>
      <InputOTPGroup>
        <InputOTPSlot index={0} />
        <InputOTPSlot index={1} />
        <InputOTPSlot index={2} />
        <InputOTPSlot index={3} />
        <InputOTPSlot index={4} />
        <InputOTPSlot index={5} />
      </InputOTPGroup>
    </InputOTP>
  );
}

With separator

<InputOTP maxLength={6} value={value} onChange={setValue}>
  <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

ComponentNotable props
InputOTPmaxLength (required), value, onChange, disabled, pattern (e.g. REGEXP_ONLY_DIGITS from input-otp), containerClassName
InputOTPGroupwraps a run of slots; first/last get outer radii automatically
InputOTPSlotindex (required) — reads char / caret / active state from OTPInputContext
InputOTPSeparatordecorative dash between groups; role="separator"

Source

packages/react/src/components/input-otp.tsx · built on input-otp