Reference index

Components

Input OTP

One-time code entry on Base UI OTP Field: square 44px cells sharing 1px ink rules, Barlow Condensed figures.

Preview

Enter the 6 digits we sent to your device.

Install

bash

npx shadcn add @eloquent/input-otp

Usage

tsx

import { Label } from "@/components/ui/label";
import { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot } from "@/components/ui/input-otp";

<Label htmlFor="code">Verification code</Label>
<InputOTP id="code" length={6} slotLabel={(n, total) => `Digit ${n} of ${total}`}>
  <InputOTPGroup>
    {[0, 1, 2].map((i) => <InputOTPSlot key={i} index={i} />)}
  </InputOTPGroup>
  <InputOTPSeparator />
  <InputOTPGroup>
    {[3, 4, 5].map((i) => <InputOTPSlot key={i} index={i} />)}
  </InputOTPGroup>
</InputOTP>

slotLabel names slots 2 to n and is required, so no English is built in. Name the first slot with a <label htmlFor> that points at id, a FieldLabel, or aria-labelledby on InputOTP; Base UI ignores aria-label on the first slot. Use onValueComplete to react when every cell is filled, or autoSubmit to submit the form.

States

Filled
Disabled
That code is incomplete. Enter all 4 digits.
StateTreatment
Empty, filled44px square cells sharing 1px ink rules; figures in Barlow Condensed 700
Presstint-1 fill. No hover effect
Focus2px ink outline, 2px offset, raised above the neighbouring cells
Invalid2px ink underline on each cell, with FieldError giving the ink icon and message
DisabledHalftone text and border, cursor-not-allowed

Keyboard

KeyAction
Tab / Shift+TabEnter and leave the code field (one tab stop)
Digits (or letters, per validationType)Fill the cell and move to the next; other characters are rejected
BackspaceClear the cell and step back
Arrow Left / RightMove between cells
PasteFills every cell from the pasted code

Vietnamese

Nhập 6 chữ số chúng tôi đã gửi tới thiết bị của bạn.

Ink adaptation

Upstream shadcn's rounded end cells, shadow, ring glow and blinking fake caret are removed. Built on Base UI's OTPField (stable in @base-ui/react 1.9.0), so there is no dependency on the input-otp package; each cell is a native input. Upstream's maxLength is length here, and slotLabel is new.