Phara UI v2.x

OTP Input

A series of individual boxes for capturing one-time passwords and verification codes. Supports auto-advance, backspace, arrow navigation, paste, and Livewire binding.

Basic

A 6-digit numeric input by default. Focus automatically advances to the next box on entry and retreats on backspace. Paste a full code to fill all boxes at once.

Blade
<x-ui::otp name="code" />
Lengths

Set the number of digit boxes with :length. Common values are 4 (PIN), 6 (TOTP), and 8 (backup code).

4 digits

6 digits

8 digits

Blade
<x-ui::otp :length="4" />
<x-ui::otp :length="6" />
<x-ui::otp :length="8" />
Sizes

Three box sizes to suit different layout densities. Default is md.

Small

Medium

Large

Blade
<x-ui::otp size="sm" />
<x-ui::otp size="md" />
<x-ui::otp size="lg" />
Alphanumeric

Set type="alphanumeric" to accept letters and numbers — useful for invite codes and backup tokens. Non-alphanumeric characters are blocked.

Blade
<x-ui::otp type="alphanumeric" :length="8" placeholder="·" />
Masked

Add mask to render each box as a password input — entered digits are hidden as bullets. Ideal for PIN entry.

Blade
<x-ui::otp :length="4" mask label="PIN" />
Separator

Add separator to render a dash at the midpoint of even-length inputs, giving the code a visual grouping.

6 digits with separator

8 digits with separator

Blade
{{-- Dash rendered at the midpoint for even lengths --}}
<x-ui::otp :length="6" separator />
<x-ui::otp :length="8" separator />
Livewire

Bind with wire:model.live. The hidden input dispatches input and change events on every keystroke so the Livewire property stays in sync.

Server value: ——————

PHP
// Livewire component
public string $code = '';

public function updatedCode(): void
{
    if (strlen($this->code) === 6) {
        // All digits filled — verify the code
    }
}

// Template
<x-ui::otp
    name="code"
    wire:model.live="code"
    :length="6"
    label="Verification code"
/>
Auto Submit

Add auto-submit to call requestSubmit() on the nearest form as soon as the last digit is filled — no confirm button needed.

Form submits automatically when all boxes are filled

Blade
{{-- Submits the nearest <form> automatically when all digits are filled --}}
<form wire:submit="submit">
    <x-ui::otp name="pin" wire:model="pin" :length="4" mask auto-submit />
</form>