OTP Input Component
Introduction
The otp
component provides a secure and user-friendly way to handle One-Time Password (OTP) input. It features automatic focus progression, paste handling, validation with custom patterns, accessibility support, and seamless integration with both Livewire and Alpine.js. Perfect for authentication flows, verification codes, and any multi-digit input scenarios.
Installation
Use the fluxtor artisan command to install the otp
component easily:
php artisan fluxtor:install otp
Basic Usage
<x-ui.otp wire:model="verificationCode" />
Bind To Livewire
To use with Livewire you need to only use wire:model="code"
to bind your OTP state:
<!-- this asume you have $verificationCode in your class component --> <div class="max-w-md mx-auto"> <x-ui.otp wire:model="verificationCode" /> </div>
Using it within Blade & Alpine
You can use it outside Livewire with just Alpine (with Blade):
<div class="max-w-md mx-auto" x-data="{ code: null }"> <x-ui.otp x-model="code" /> </div>
Because we're making this possible using (like) the x-modelable
API, so you can't use state
as a variable name because the component uses it internally.
Customization
Custom Length
Control the number of input fields with the length
parameter.
<x-ui.otp wire:model="code4" :length="4" /> <x-ui.otp wire:model="code6" :length="6" /> <x-ui.otp wire:model="code8" :length="8" />
Sloted Inputs
you can pass the individual inputs as a slot and you tweack it as you need
note we're using
<x-ui.otp.input>
not the native input
<x-ui.otp wire:model="code" > <x-ui.otp.input class="rounded-full m-2" /> <x-ui.otp.input class="rounded-full m-2"/> <x-ui.otp.input class="rounded-full m-2"/> <x-ui.otp.input class="rounded-full m-2"/> <x-ui.otp.input class="rounded-full m-2"/> </x-ui.otp>
Separator
<x-ui.otp wire:model="code" > <x-ui.otp.input /> <x-ui.otp.input/> <x-ui.otp.separator/> <x-ui.otp.input /> <x-ui.otp.input /> <x-ui.otp.separator/> <x-ui.otp.input /> <x-ui.otp.input /> </x-ui.otp>
Input Types and Validation
Control what characters are allowed with different input types and patterns.
<x-ui.otp wire:model="numericCode" allowedPattern="[0-9]" /> <x-ui.otp wire:model="alphanumericCode" allowedPattern="[A-Za-z0-9]" /> <x-ui.otp wire:model="letterCode" allowedPattern="[A-Za-z]" />
AutoFocus
to focus the first relevent input in the initialization phase you may use the autofocus
<x-ui.otp
...
autofocus
/>
Advanced Features
Pre-filled Values
The component automatically handles external state synchronization and can display pre-filled values.
Current value:
<div x-data="{ code: '1234' }"> <x-ui.otp x-model="code" /> </div>
Paste Handling
The component intelligently handles pasted content, filtering valid characters and auto-filling inputs.
The component will extract valid digits and fill the inputs automatically.
Real-time Validation
Monitor input changes in real-time with Alpine.js effects.
<div x-data="{ code: null, isValid: false, }" x-init=" queueMicrotask(() => { Alpine.effect(() => { console.log('here') isValid = code && code.length === 4; }); }); " > <label class="block text-sm font-medium mb-2">Enter 4-digit code</label> <x-ui.otp x-model="code" /> <div class="mt-2"> <span x-show="isValid" style="display: none;" class="text-green-600 text-sm">✓ Valid code entered</span> <span x-show="!isValid" style="display: none;" class="text-red-600 text-sm">Please enter a complete 4-digit code</span> </div> </div>
Component Props
Prop Name | Type | Default | Required | Description |
---|---|---|---|---|
length |
integer | 4 |
No | Number of input fields to render |
type |
string | 'text' |
No | HTML input type attribute |
allowedPattern |
string | '[0-9]' |
No | Regex pattern for allowed characters |
wire:model |
string | - | Yes* | Livewire property to bind to |
x-model |
string | - | Yes* | Alpine.js property to bind to |
class |
string | 'contents' |
No | Additional CSS classes for container |
*Either wire:model
or x-model
is required
Technical Notes
- Uses
queueMicrotask()
to prevent race conditions during DOM updates - Synchronizes external state changes automatically
- Handles edge cases like partial pastes and invalid character filtering