otp-input-kit

A highly customizable, framework-agnostic OTP input library with full RTL support, accessibility, i18n, timer, and Web Component.

Zero dependencies ES Module + UMD Full RTL & i18n WCAG 2.1 AA Web Component Dark mode

Installation

📦 NPM

Import in your project:

🌐 CDN (UMD)

Then use global variable:

Basic Usage

Choose your preferred way to integrate the library into your project.

🚀 JavaScript API

🧩 Web Component

🔢 Basic 6-Digit Numeric
Auto-focus, smart paste, backspace navigation, undo/redo (Ctrl+Z / Ctrl+Shift+Z)
Enter your 6-digit code
🔤 RTL — Arabic (العربية)
اتجاه من اليمين إلى اليسار مع الأرقام العربية-الهندية وحركة المؤشر المعكوسة
أدخل رمز التحقق
🇮🇷 RTL — Persian (فارسی)
اعداد فارسی با پشتیبانی کامل RTL
کد خود را وارد کنید
🔒 Secure Mode (Masked)
Input masked like a password field — prevents shoulder-surfing
Enter PIN (masked)
⏱ Timer + Resend + Auto-submit
Countdown with progress bar — expires, disables inputs, shows resend button
Enter code within the time limit
🔡 Alphanumeric + Custom Validation
Accepts A–Z and 0–9; custom validator rejects patterns starting with "00"
Enter 6-character alphanumeric code
💥 Error Animation Styles
Three built-in error animations — click any button to see them in action. Type a wrong code or use the buttons below.
shake Horizontal wobble — most familiar feedback pattern
highlight Subtle red flash — less intrusive, good for partial errors
both Combines shake + highlight + haptic vibration on mobile
false No animation — just the red border state (a11y-only)
Live validation
Type any code starting with 000 to trigger the error animation automatically.
Try entering "000000" or any code starting with 0
Single-digit shake on invalid character
Numeric-only input — try typing a letter; only that one cell shakes.
📱 4-Digit PIN (Mobile-optimized)
Haptic feedback, numeric keyboard, mobile auto-fill (autocomplete="one-time-code")
Enter your 4-digit PIN
🧩 8-Digit Hex Code
Accepts 0-9, A-F only — useful for activation keys
Enter 8-character hex code
📋 Live Event Log
See every event as it fires in real time

Input Themes

Use theme: 'soft' in options or data-theme="soft" on the container.

Default
Underline
Rounded
Pill
Ghost
Filled
Soft (Purple)
Neon
Gradient
Elevated 3D
Custom CSS Vars
Dark

Toast Notifications

6 toast themes × 4 types (success / error / warning / info). Auto-dismiss with progress bar, pause on hover, RTL-aware, and accessible (ARIA live regions).

🍞 Toast Theme Showcase
Click any chip to fire a toast. Hover to pause auto-dismiss.
Default
Glass (frosted)
Solid
Gradient
Minimal
Pill (compact)
Position:
🎯 OTP with Auto-Toast Integration
Toast fires automatically on complete / error / expire / resend

Digit Separators

➖ Custom Digit Separators
Visual separators between digit groups — dash, dot, space, or any character
Dash ( 3 + 3 )
Bullet ( 2 + 2 + 2 )
Em dash ( 4 + 4 )

SMS OTP Auto-Read

📱 Web OTP API — Auto-Fill from SMS
On Android Chrome, the browser reads the OTP from an incoming SMS and fills the inputs automatically
Waiting for SMS… (requires Android + Chrome + HTTPS)
Required SMS format:
Your code is 123456

@yourdomain.com #123456

Biometric Confirm

🔐 Biometric Confirm Step (WebAuthn)
After the OTP is accepted, request fingerprint / Face ID / Windows Hello as a second factor
Fill the OTP — then approve the biometric prompt
Checking platform authenticator…

Web Component

🧱 <otp-input> Custom Element
Drop in anywhere — no JavaScript required in markup
Waiting for web component input…

API Reference

Methods
Method Description
getValue() Returns current OTP value as western-digit string
setValue(value) Programmatically set OTP value
clear() Clear all inputs and re-focus first
focus(index) Focus a specific digit by index
disable() Disable all inputs
enable() Re-enable inputs
setError(msg) Trigger error animation + announce to screen reader
clearError() Remove error state from all inputs
resetTimer(dur) Reset and restart countdown
setDirection(dir) Dynamically switch 'ltr' / 'rtl'
setLocale(locale) Switch locale (updates numeral rendering)
on(event, fn) Subscribe to events. Returns unsubscribe function.
destroy() Destroy instance, clean up all DOM and listeners
Events
Event Payload Description
change string Fires on every keystroke with current value
complete string All digits filled and validation passed
error Error[] Validation failed
focus { index, input } A digit gained focus
blur { index, input } A digit lost focus
expire Timer reached zero
resend User clicked resend button
Key Options
Option Type Default Description
length number 6 Number of OTP digits
type string 'numeric' 'numeric' | 'alpha' | 'alphanumeric' | 'hex' | 'custom'
pattern RegExp null Custom character pattern (when type='custom')
secure boolean false Mask input values (type="password")
direction string 'auto' 'ltr' | 'rtl' | 'auto' (reads from DOM)
locale string null BCP 47 locale for number rendering + direction
nativeNumerals boolean false Render locale-native digits (Arabic-Indic, etc.)
autoSubmit boolean false Submit closest form on completion
haptic boolean true Vibration API feedback on mobile
clipboardDetection boolean true Suggest pasting if OTP-like text in clipboard
validate function null (value) => errorMsg | null
animation.error string 'shake' 'shake' | 'highlight' | 'both' | false
timer.enabled boolean false Show countdown timer
timer.duration number 60 Timer duration in seconds
resend.enabled boolean false Show resend button after expiry