OTP / PIN Input
Verification code input with individual character boxes. Use for OTP codes, PINs, and other segmented numeric inputs. Supports masked mode for secure entry.
Default
Standard 6-digit verification code input.
Enter the 6-digit code sent to your email
<div class="vt-flex vt-items-center vt-gap-2" data-otp="">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-1-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-1-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-1-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-1-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-1-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-1-1">
</div>
<p class="vt-text-sm vt-text-foreground-muted" id="otp-input-1-1">Enter the 6-digit code sent to your email</p>
4-Digit
Shorter 4-digit verification code input.
Enter your 4-digit code
<div class="vt-flex vt-items-center vt-gap-2" data-otp="">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-2-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-2-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-2-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-2-1">
</div>
<p class="vt-text-sm vt-text-foreground-muted" id="otp-input-2-1">Enter your 4-digit code</p>
With Separator
6-digit code split into two groups of three with a dash separator.
<div class="vt-flex vt-items-center vt-gap-2" data-otp="">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value">
<span class="vt-text-xl vt-text-foreground-muted vt-font-mono vt-px-1">–</span>
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value">
</div>
Masked
Input with masked values for secure PIN entry.
PIN is hidden for security
<div class="vt-flex vt-items-center vt-gap-3" data-otp="">
<div class="vt-otp-cell vt-flex vt-items-center vt-justify-center vt-text-xl">●</div>
<div class="vt-otp-cell vt-flex vt-items-center vt-justify-center vt-text-xl">●</div>
<div class="vt-otp-cell vt-flex vt-items-center vt-justify-center vt-text-xl">●</div>
<div class="vt-otp-cell vt-flex vt-items-center vt-justify-center vt-text-xl">●</div>
</div>
<p class="vt-text-sm vt-text-foreground-muted">PIN is hidden for security</p>
With Label
Input with a descriptive label above.
4-digit numeric code
<div class="vt-flex vt-flex-col vt-items-center vt-gap-3">
<label class="vt-text-sm vt-font-medium vt-text-foreground-primary">Enter your PIN</label>
<div class="vt-flex vt-items-center vt-gap-3" data-otp="">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-5-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-5-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-5-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-5-1">
</div>
<p class="vt-text-sm vt-text-foreground-muted" id="otp-input-5-1">4-digit numeric code</p>
</div>
Sizes
Small and large size variants.
Small
Large
<div>
<p class="vt-text-xs vt-font-medium vt-text-foreground-muted vt-mb-2 vt-text-center" id="otp-input-6-1">Small</p>
<div class="vt-flex vt-items-center vt-gap-2" data-otp="">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell vt-w-8 vt-h-10 vt-text-sm" aria-label="Value" aria-describedby="otp-input-6-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell vt-w-8 vt-h-10 vt-text-sm" aria-label="Value" aria-describedby="otp-input-6-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell vt-w-8 vt-h-10 vt-text-sm" aria-label="Value" aria-describedby="otp-input-6-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell vt-w-8 vt-h-10 vt-text-sm" aria-label="Value" aria-describedby="otp-input-6-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell vt-w-8 vt-h-10 vt-text-sm" aria-label="Value" aria-describedby="otp-input-6-1">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell vt-w-8 vt-h-10 vt-text-sm" aria-label="Value" aria-describedby="otp-input-6-1">
</div>
</div>
<div>
<p class="vt-text-xs vt-font-medium vt-text-foreground-muted vt-mb-2 vt-text-center" id="otp-input-6-2">Large</p>
<div class="vt-flex vt-items-center vt-gap-3" data-otp="">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell vt-w-12 vt-h-14 vt-text-xl" aria-label="Value" aria-describedby="otp-input-6-2">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell vt-w-12 vt-h-14 vt-text-xl" aria-label="Value" aria-describedby="otp-input-6-2">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell vt-w-12 vt-h-14 vt-text-xl" aria-label="Value" aria-describedby="otp-input-6-2">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell vt-w-12 vt-h-14 vt-text-xl" aria-label="Value" aria-describedby="otp-input-6-2">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell vt-w-12 vt-h-14 vt-text-xl" aria-label="Value" aria-describedby="otp-input-6-2">
<input type="text" inputmode="numeric" maxlength="1" class="vt-otp-cell vt-w-12 vt-h-14 vt-text-xl" aria-label="Value" aria-describedby="otp-input-6-2">
</div>
</div>
Filled State
Input with values already entered.
Code entered successfully
<div class="vt-flex vt-items-center vt-gap-2" data-otp="">
<input type="text" inputmode="numeric" maxlength="1" value="4" readonly="" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-7-1">
<input type="text" inputmode="numeric" maxlength="1" value="2" readonly="" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-7-1">
<input type="text" inputmode="numeric" maxlength="1" value="8" readonly="" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-7-1">
<input type="text" inputmode="numeric" maxlength="1" value="1" readonly="" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-7-1">
<input type="text" inputmode="numeric" maxlength="1" value="5" readonly="" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-7-1">
<input type="text" inputmode="numeric" maxlength="1" value="6" readonly="" class="vt-otp-cell" aria-label="Value" aria-describedby="otp-input-7-1">
</div>
<p class="vt-text-sm vt-text-foreground-muted" id="otp-input-7-1">Code entered successfully</p>
Error State
Displays validation error when the entered code is incorrect.
Invalid verification code. Please try again.
<div class="vt-flex vt-items-center vt-gap-2" data-otp="">
<input type="text" inputmode="numeric" maxlength="1" value="7" readonly="" class="vt-otp-cell vt-border-error-fill" aria-label="Value" aria-invalid="true" aria-describedby="otp-input-8-1">
<input type="text" inputmode="numeric" maxlength="1" value="3" readonly="" class="vt-otp-cell vt-border-error-fill" aria-label="Value" aria-invalid="true" aria-describedby="otp-input-8-1">
<input type="text" inputmode="numeric" maxlength="1" value="9" readonly="" class="vt-otp-cell vt-border-error-fill" aria-label="Value" aria-invalid="true" aria-describedby="otp-input-8-1">
<input type="text" inputmode="numeric" maxlength="1" value="0" readonly="" class="vt-otp-cell vt-border-error-fill" aria-label="Value" aria-invalid="true" aria-describedby="otp-input-8-1">
<input type="text" inputmode="numeric" maxlength="1" value="4" readonly="" class="vt-otp-cell vt-border-error-fill" aria-label="Value" aria-invalid="true" aria-describedby="otp-input-8-1">
<input type="text" inputmode="numeric" maxlength="1" value="2" readonly="" class="vt-otp-cell vt-border-error-fill" aria-label="Value" aria-invalid="true" aria-describedby="otp-input-8-1">
</div>
<p class="vt-text-sm vt-text-error-fill" id="otp-input-8-1">Invalid verification code. Please try again.</p>
Success State
Input showing successful validation.
<div class="vt-flex vt-items-center vt-gap-3" data-otp="">
<div class="vt-otp-cell vt-flex vt-items-center vt-justify-center vt-text-xl vt-border-success-fill">●</div>
<div class="vt-otp-cell vt-flex vt-items-center vt-justify-center vt-text-xl vt-border-success-fill">●</div>
<div class="vt-otp-cell vt-flex vt-items-center vt-justify-center vt-text-xl vt-border-success-fill">●</div>
<div class="vt-otp-cell vt-flex vt-items-center vt-justify-center vt-text-xl vt-border-success-fill">●</div>
</div>
<div class="vt-flex vt-items-center vt-gap-1.5 vt-text-info-fill">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-check vt-w-4 vt-h-4">
<path d="M20 6 9 17l-5-5"></path>
</svg>
<span class="vt-text-sm vt-font-medium">PIN verified successfully</span>
</div>
Guidelines
One-time verification codes, one box per digit.
API Reference
All utility classes available for the OTP Input component.
| Class | Type | Description |
|---|---|---|
vt-w-10 vt-h-12 |
Size | Default input box size (40×48px) |
vt-w-8 vt-h-10 |
Size | Small input box size (32×40px) |
vt-w-12 vt-h-14 |
Size | Large input box size (48×56px) |
vt-text-center vt-font-mono |
Text | Centered monospace text for digits |
vt-border-error-fill |
State | Error state border color |
vt-border-success-fill |
State | Success state border color |
inputmode="numeric" |
Attribute | Mobile keyboard shows numeric keypad |
maxlength="1" |
Attribute | Restricts input to single character |
Accessibility
Keyboard and screen reader support.
| Feature | Details |
|---|---|
| Auto-advance | Input automatically moves focus to next box when filled |
| Backspace | Backspace moves focus to previous box when current is empty |
| Paste Support | Pasting full code distributes digits across all inputs |
| ARIA Label | Use aria-label on each input: "Digit 1 of 6", "Digit 2 of 6", etc. |
| Error Feedback | Use aria-invalid and role="alert" for error messages |