

<Preview name="InputOTPStatesExample" />

## Overview [#overview]

The `InputOTP` component provides a user-friendly interface for entering one-time passwords or verification codes. It features animated character slots, customizable grouping with separators, and supports validation states.

## Usage [#usage]

```tsx
import {
  InputOTP,
  InputOTPGroup,
  InputOTPSeparator,
  InputOTPSlot,
} from "@tilt-legal/cubitt-components/input-otp";
```

```tsx
<InputOTP maxLength={6}>
  <InputOTPGroup>
    <InputOTPSlot index={0} />
    <InputOTPSlot index={1} />
    <InputOTPSlot index={2} />
  </InputOTPGroup>
  <InputOTPSeparator />
  <InputOTPGroup>
    <InputOTPSlot index={3} />
    <InputOTPSlot index={4} />
    <InputOTPSlot index={5} />
  </InputOTPGroup>
</InputOTP>
```

## Examples [#examples]

### With Multiple Separators [#with-multiple-separators]

OTP input with multiple groups and separators for credit card-style formatting.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="InputOTPWithSeparatorExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import {
      InputOTP,
      InputOTPGroup,
      InputOTPSeparator,
      InputOTPSlot,
    } from "@tilt-legal/cubitt-components/input-otp";

    <InputOTP maxLength={6}>
      <InputOTPGroup>
        <InputOTPSlot index={0} />
        <InputOTPSlot index={1} />
      </InputOTPGroup>
      <InputOTPSeparator />
      <InputOTPGroup>
        <InputOTPSlot index={2} />
        <InputOTPSlot index={3} />
      </InputOTPGroup>
      <InputOTPSeparator />
      <InputOTPGroup>
        <InputOTPSlot index={4} />
        <InputOTPSlot index={5} />
      </InputOTPGroup>
    </InputOTP>;
    ```
  </Tab>
</Tabs>

### Numbers Only [#numbers-only]

OTP input restricted to numeric characters only using a regex pattern.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="InputOTPPatternExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import {
      InputOTP,
      InputOTPGroup,
      InputOTPSlot,
    } from "@tilt-legal/cubitt-components/input-otp";

    <InputOTP maxLength={6} pattern="^[0-9]*$">
      <InputOTPGroup>
        <InputOTPSlot index={0} />
        <InputOTPSlot index={1} />
        <InputOTPSlot index={2} />
        <InputOTPSlot index={3} />
        <InputOTPSlot index={4} />
        <InputOTPSlot index={5} />
      </InputOTPGroup>
    </InputOTP>;
    ```
  </Tab>
</Tabs>

### States [#states]

Switch between default, error, and disabled states.

<Tabs className="bg-transparent border-none rounded-none" items="['Preview', 'Code']">
  <Tab value="Preview" className="p-0">
    <Preview name="InputOTPStatesExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import {
      InputOTP,
      InputOTPGroup,
      InputOTPSeparator,
      InputOTPSlot,
    } from "@tilt-legal/cubitt-components/input-otp";

    const states = ["default", "invalid", "disabled"] as const;
    const [state, setState] =
      useState<"default" | "invalid" | "disabled">("default");

    <>
      <InputOTP
        disabled={state === "disabled"}
        invalid={state === "invalid"}
        maxLength={6}
      >
        <InputOTPGroup>
          <InputOTPSlot index={0} />
          <InputOTPSlot index={1} />
          <InputOTPSlot index={2} />
        </InputOTPGroup>
        <InputOTPSeparator />
        <InputOTPGroup>
          <InputOTPSlot index={3} />
          <InputOTPSlot index={4} />
          <InputOTPSlot index={5} />
        </InputOTPGroup>
      </InputOTP>
      <PreviewFooter>
        <ToggleGroup
          aria-label="Input OTP state"
          groupVariant="segmented"
          multiple={false}
          onValueChange={(value) => {
            if (states.includes(value as (typeof states)[number])) {
              setState(value as (typeof states)[number]);
            }
          }}
          value={state}
        >
          <ToggleGroupItem value="default">Default</ToggleGroupItem>
          <ToggleGroupItem value="invalid">Error</ToggleGroupItem>
          <ToggleGroupItem value="disabled">Disabled</ToggleGroupItem>
        </ToggleGroup>
      </PreviewFooter>
    </>;
    ```
  </Tab>
</Tabs>

***

## API Reference [#api-reference]

### InputOTP [#inputotp]

The root component that manages the OTP input state. Built on [input-otp](https://input-otp.rodz.dev).

| Prop                 | Type                      | Default | Description                                                      |
| -------------------- | ------------------------- | ------- | ---------------------------------------------------------------- |
| `maxLength`          | `number`                  | -       | Maximum number of characters (required)                          |
| `value`              | `string`                  | -       | Controlled value                                                 |
| `onChange`           | `(value: string) => void` | -       | Callback when value changes                                      |
| `onComplete`         | `(value: string) => void` | -       | Callback when all slots are filled                               |
| `pattern`            | `string`                  | -       | Regex pattern for allowed characters                             |
| `invalid`            | `boolean`                 | `false` | Shows invalid/error styling on all slots and sets `aria-invalid` |
| `disabled`           | `boolean`                 | `false` | Disables the input                                               |
| `containerClassName` | `string`                  | -       | Class name for the container element                             |

### InputOTPGroup [#inputotpgroup]

Groups slots together visually.

| Prop        | Type     | Default | Description            |
| ----------- | -------- | ------- | ---------------------- |
| `className` | `string` | -       | Additional CSS classes |

### InputOTPSlot [#inputotpslot]

Individual character slot that displays a single character.

| Prop        | Type     | Default | Description                    |
| ----------- | -------- | ------- | ------------------------------ |
| `index`     | `number` | -       | Slot position index (required) |
| `className` | `string` | -       | Additional CSS classes         |

### InputOTPSeparator [#inputotpseparator]

Visual separator between slot groups.

| Prop        | Type     | Default | Description            |
| ----------- | -------- | ------- | ---------------------- |
| `className` | `string` | -       | Additional CSS classes |
