# InputOTP · HeroUI

> A one-time password input component for verification codes and secure authentication

- Page: https://jiguang132.com/systems/heroui/docs/components/input-otp
- Based on: HeroUI documentation (Apache-2.0) @ 60edd8ed751b1d2a270623fbb182bbcfa8baa9af

## Import

```tsx
import { InputOTP } from '@heroui/react';
```

### Usage


> Example `input-otp-basic`: interactive preview on https://jiguang132.com/systems/heroui/docs/components/input-otp


### Anatomy

Import the InputOTP component and access all parts using dot notation.

```tsx
import { InputOTP } from '@heroui/react';

export default () => (
  <InputOTP maxLength={6}>
    <InputOTP.Group>
      <InputOTP.Slot index={0} />
      <InputOTP.Slot index={1} />
      {/* ...rest of the slots */}
    </InputOTP.Group>
    <InputOTP.Separator />
    <InputOTP.Group>
      <InputOTP.Slot index={3} />
      {/* ...rest of the slots */}
    </InputOTP.Group>
  </InputOTP>
)
```

> **InputOTP** is built on top of [input-otp](https://github.com/guilhermerodz/input-otp) by [@guilherme_rodz](https://twitter.com/guilherme_rodz), providing a flexible and accessible foundation for OTP input components.

### Four Digits


> Example `input-otp-four-digits`: interactive preview on https://jiguang132.com/systems/heroui/docs/components/input-otp


### Disabled State


> Example `input-otp-disabled`: interactive preview on https://jiguang132.com/systems/heroui/docs/components/input-otp


### With Pattern

Use the `pattern` prop to restrict input to specific characters. HeroUI exports common patterns like `REGEXP_ONLY_CHARS` and `REGEXP_ONLY_DIGITS`.


> Example `input-otp-with-pattern`: interactive preview on https://jiguang132.com/systems/heroui/docs/components/input-otp


### Controlled

Control the value to synchronize with state, clear the input, or implement custom validation.


> Example `input-otp-controlled`: interactive preview on https://jiguang132.com/systems/heroui/docs/components/input-otp


### With Validation

Use `isInvalid` together with validation messages to surface errors.


> Example `input-otp-with-validation`: interactive preview on https://jiguang132.com/systems/heroui/docs/components/input-otp


### On Complete

Use the `onComplete` callback to trigger actions when all slots are filled.


> Example `input-otp-on-complete`: interactive preview on https://jiguang132.com/systems/heroui/docs/components/input-otp


### Form Example

A complete two-factor authentication form with validation and submission.


> Example `input-otp-form-example`: interactive preview on https://jiguang132.com/systems/heroui/docs/components/input-otp


### Variants

The InputOTP component supports two visual variants:

- **`primary`** (default) - Standard styling with shadow, suitable for most use cases
- **`secondary`** - Lower emphasis variant without shadow, suitable for use in Surface components


> Example `input-otp-variants`: interactive preview on https://jiguang132.com/systems/heroui/docs/components/input-otp


### In Surface

When used inside a [Surface](/systems/heroui/docs/components/surface) component, use `variant="secondary"` to apply the lower emphasis variant suitable for surface backgrounds.


> Example `input-otp-on-surface`: interactive preview on https://jiguang132.com/systems/heroui/docs/components/input-otp


## Styling

### Passing Tailwind CSS classes

```tsx
import {InputOTP, Label} from '@heroui/react';

function CustomInputOTP() {
  return (
    <div className="flex flex-col gap-2">
      <Label className="text-sm font-semibold">Enter verification code</Label>
      <InputOTP
        className="gap-3"
        containerClassName="gap-4"
        maxLength={6}
      >
        <InputOTP.Group className="gap-3">
          <InputOTP.Slot
            className="size-12 rounded-lg border-2 text-lg font-bold"
            index={0}
          />
          <InputOTP.Slot
            className="size-12 rounded-lg border-2 text-lg font-bold"
            index={1}
          />
          <InputOTP.Slot
            className="size-12 rounded-lg border-2 text-lg font-bold"
            index={2}
          />
        </InputOTP.Group>
        <InputOTP.Separator className="bg-border h-1 w-2 rounded-full" />
        <InputOTP.Group className="gap-3">
          <InputOTP.Slot
            className="size-12 rounded-lg border-2 text-lg font-bold"
            index={3}
          />
          <InputOTP.Slot
            className="size-12 rounded-lg border-2 text-lg font-bold"
            index={4}
          />
          <InputOTP.Slot
            className="size-12 rounded-lg border-2 text-lg font-bold"
            index={5}
          />
        </InputOTP.Group>
      </InputOTP>
    </div>
  );
}
```

### Customizing the component classes

To customize the InputOTP component classes, you can use the `@layer components` directive.
  
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).

```css
@layer components {
  .input-otp {
    @apply gap-3;
  }

  .input-otp__slot {
    @apply size-12 rounded-xl border-2 font-bold;
  }

  .input-otp__slot[data-active="true"] {
    @apply border-primary-500 ring-2 ring-primary-200;
  }

  .input-otp__separator {
    @apply w-2 h-1 bg-border-strong rounded-full;
  }
}
```

HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.

### CSS Classes

The InputOTP component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/input-otp.css)):

#### Base Classes
- `.input-otp` - Base container
- `.input-otp__container` - Inner container from input-otp library
- `.input-otp__group` - Group of slots
- `.input-otp__slot` - Individual input slot
- `.input-otp__slot-value` - The character inside a slot
- `.input-otp__caret` - Blinking caret indicator
- `.input-otp__separator` - Visual separator between groups

#### State Classes
- `.input-otp__slot[data-active="true"]` - Currently active slot
- `.input-otp__slot[data-filled="true"]` - Slot with a character
- `.input-otp__slot[data-disabled="true"]` - Disabled slot
- `.input-otp__slot[data-invalid="true"]` - Invalid slot
- `.input-otp__container[data-disabled="true"]` - Disabled container

### Interactive States

The component supports both CSS pseudo-classes and data attributes for flexibility:

- **Hover**: `:hover` or `[data-hovered="true"]` on slot
- **Active**: `[data-active="true"]` on slot (currently focused)
- **Filled**: `[data-filled="true"]` on slot (contains a character)
- **Disabled**: `[data-disabled="true"]` on container and slots
- **Invalid**: `[data-invalid="true"]` on slots

## API Reference

### InputOTP Props

InputOTP is built on top of the [input-otp](https://github.com/guilhermerodz/input-otp) library with additional features.

#### Base Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `maxLength` | `number` | - | **Required.** Number of input slots. |
| `value` | `string` | - | Controlled value (uncontrolled if not provided). |
| `onChange` | `(value: string) => void` | - | Handler called when the value changes. |
| `onComplete` | `(value: string) => void` | - | Handler called when all slots are filled. |
| `className` | `string` | - | Additional CSS classes for the container. |
| `containerClassName` | `string` | - | CSS classes for the inner container. |
| `variant` | `"primary" \| "secondary"` | `"primary"` | Visual variant of the component. `primary` is the default style with shadow. `secondary` is a lower emphasis variant without shadow, suitable for use in surfaces. |
| `children` | `React.ReactNode` | - | InputOTP.Group, InputOTP.Slot, and InputOTP.Separator components. |

#### Validation Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `isDisabled` | `boolean` | `false` | Whether the input is disabled. |
| `isInvalid` | `boolean` | `false` | Whether the input is in an invalid state. |
| `validationErrors` | `string[]` | - | Server-side or custom validation errors. |
| `validationDetails` | `ValidityState` | - | HTML5 validation details. |

#### Input Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `pattern` | `string` | - | Regex pattern for allowed characters (e.g., `REGEXP_ONLY_DIGITS`). |
| `textAlign` | `'left' \| 'center' \| 'right'` | `'left'` | Text alignment within slots. |
| `inputMode` | `'numeric' \| 'text' \| 'decimal' \| 'tel' \| 'search' \| 'email' \| 'url'` | `'numeric'` | Virtual keyboard type on mobile devices. |
| `placeholder` | `string` | - | Placeholder text for empty slots. |
| `pasteTransformer` | `(text: string) => string` | - | Transform pasted text (e.g., remove hyphens). |

#### Form Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `name` | `string` | - | Name attribute for form submission. |
| `autoFocus` | `boolean` | - | Whether to focus the first slot on mount. |

### InputOTP.Group Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `className` | `string` | - | Additional CSS classes for the group. |
| `children` | `React.ReactNode` | - | InputOTP.Slot components. |

### InputOTP.Slot Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `index` | `number` | - | **Required.** Zero-based index of the slot. |
| `className` | `string` | - | Additional CSS classes for the slot. |

### InputOTP.Separator Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `className` | `string` | - | Additional CSS classes for the separator. |

### Exported Patterns

HeroUI re-exports common regex patterns from input-otp for convenience:

```tsx
import { REGEXP_ONLY_DIGITS, REGEXP_ONLY_CHARS, REGEXP_ONLY_DIGITS_AND_CHARS } from '@heroui/react';

// Use with pattern prop
<InputOTP pattern={REGEXP_ONLY_DIGITS} maxLength={6}>
  {/* ... */}
</InputOTP>
```

- **REGEXP_ONLY_DIGITS** - Only numeric characters (0-9)
- **REGEXP_ONLY_CHARS** - Only alphabetic characters (a-z, A-Z)
- **REGEXP_ONLY_DIGITS_AND_CHARS** - Alphanumeric characters (0-9, a-z, A-Z)

---

Index of all JGuang resources: https://jiguang132.com/llms.txt
