InputOTP

Accessible one-time-code input built on Base UI OTP Field.

Quick Preview

Enter the code sent to your phone.

Usage

import {
  InputOTP,
  InputOTPGroup,
  InputOTPSlot,
} from "@giddaa-housing/ui/input-otp";

<InputOTP length={4} name="code">
  <InputOTPGroup>
    <InputOTPSlot aria-label="Digit 1 of 4" />
    <InputOTPSlot aria-label="Digit 2 of 4" />
    <InputOTPSlot aria-label="Digit 3 of 4" />
    <InputOTPSlot aria-label="Digit 4 of 4" />
  </InputOTPGroup>
</InputOTP>

InputOTPSlot uses its render order; unlike input-otp-based implementations, it does not require an index prop. Render exactly the number of slots passed to length.

Examples

Sizes

Use size on InputOTP to scale every slot. The value also inherits from InputSizeProvider when size is omitted.

Props

Prop/APITypeDefaultDescription
lengthnumberrequiredNumber of slots and maximum code length.
size`"sm""md""lg"
validationType`"numeric""alpha""alphanumeric"
value / defaultValuestring-Controlled or initial uncontrolled value.
onValueChange(value, eventDetails) => void-Runs when the normalized code changes.
onValueComplete(value, eventDetails) => void-Runs after every slot is filled.
InputOTPGroupdiv props-Joins adjacent slots into a rounded group.
InputOTPSlotBase UI OTP input props-A native input for one character.
InputOTPSeparatorBase UI separator props-Visual and semantic separator between groups.

Accessibility

  • Associate the first slot with a visible label by passing id to InputOTP and matching it with htmlFor on the label.
  • Add an aria-label to every remaining slot, including its position and total count.
  • Keep autoComplete="one-time-code" enabled unless the field is not used for a one-time code.
  • Base UI provides keyboard navigation, paste distribution, validation, and native form integration.

On this page