Moul UIBeta
Components

InputOTP

An accessible, customizable, and composable One-Time Password input component.

OTP, InputOTP, One-Time Passcode, Verification Code, Caret, Separator, input-otp

InputOTP

Preview

Interactive
Please enter the 6-digit code sent to your phone.

Properties

Size
Live Code Snippet
import {
  InputOTP,
  InputOTPGroup,
  InputOTPSlot,
  InputOTPSeparator,
} from '@moul-dev/ui';
import { useState } from 'react';

export default function Example() {
  const [value, setValue] = useState('');

  return (
    <InputOTP
      value={value}
      onChange={setValue} label="One-Time Password" description="Please enter the 6-digit code sent to your phone." errorMessage="The code is invalid."
    >
      <InputOTPGroup>
        <InputOTPSlot index={0} />
        <InputOTPSlot index={1} />
        <InputOTPSlot index={2} />
      </InputOTPGroup>
      <InputOTPSeparator />
      <InputOTPGroup>
        <InputOTPSlot index={3} />
        <InputOTPSlot index={4} />
        <InputOTPSlot index={5} />
      </InputOTPGroup>
    </InputOTP>
  );
}

The InputOTP component is a flexible, highly accessible one-time password input component. It is built on top of the headless input-otp library by @guilhermerodz and styled using StyleX.

Import

import {
  InputOTP,
  InputOTPGroup,
  InputOTPSlot,
  InputOTPSeparator
} from '@moul-dev/ui';

Features

Basic Layout (6-digit)

A standard 6-digit passcode layout utilizing a separator in the middle.

Default (6 Digits with Separator)

Value:

With Form Labels & Description

Enter the 4-digit code sent to your phone.

Invalid State with Error Message

import { useState } from 'react';
import {
  InputOTP,
  InputOTPGroup,
  InputOTPSlot,
  InputOTPSeparator
} from '@moul-dev/ui';

export default function Example() {
  const [value, setValue] = useState('');

  return (
    <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>
  );
}

Label & Helper Text

The component supports standard form control label and description props.

<InputOTP
  maxLength={4}
  label="Security Code"
  description="Enter the 4-digit code sent to your email."
>
  <InputOTPGroup>
    <InputOTPSlot index={0} />
    <InputOTPSlot index={1} />
    <InputOTPSlot index={2} />
    <InputOTPSlot index={3} />
  </InputOTPGroup>
</InputOTP>

Validation State

Marking the input as invalid highlights the slot borders and renders a custom error message.

<InputOTP
  maxLength={4}
  label="Verification Code"
  isInvalid={true}
  errorMessage="The verification code you entered is incorrect."
>
  <InputOTPGroup>
    <InputOTPSlot index={0} />
    <InputOTPSlot index={1} />
    <InputOTPSlot index={2} />
    <InputOTPSlot index={3} />
  </InputOTPGroup>
</InputOTP>

Custom Separator

You can provide any React node inside InputOTPSeparator to customize the visual divider.

<InputOTP maxLength={4}>
  <InputOTPGroup>
    <InputOTPSlot index={0} />
    <InputOTPSlot index={1} />
  </InputOTPGroup>
  <InputOTPSeparator>-</InputOTPSeparator>
  <InputOTPGroup>
    <InputOTPSlot index={2} />
    <InputOTPSlot index={3} />
  </InputOTPGroup>
</InputOTP>

On this page