OTP Input
Customizable OTP input system with multi-field inputs, paste handling, keyboard navigation, and password masking.
Usage
npm install @frjoy/otpLive Demo 1: Basic OTP
Entered OTP: -
<Root onChange={setOtp} type="number" password>
<Label>Enter OTP</Label>
{[...Array(6)].map((_, i) => (
<Input key={i} length={1} />
))}
</Root>Live Demo 2: Alphanumeric OTP with Joiner
This example shows a referral-style OTP code joined with -.
Joined Code: -
<Root onChange={setOtp} type="text" joiner="-">
<Label>Referral Code</Label>
{[...Array(4)].map((_, i) => (
<Input key={i} length={2} />
))}
</Root>Props Reference
<Root />
onChange?: (otp: string) => voidtype?: 'number' | 'text' | 'any'password?: booleanjoiner?: stringpattern?: string
<Input />
length?: numberpassword?: boolean- Supports all native input props
<Label />
- Automatically focuses first incomplete field
- Accessible via
aria-live
Interactive Playground
Experiment with different props and see the changes in real-time.
Quick Presets
Configuration
Live Preview
Output:
No input yet
Length: 0 characters
Expected total: 6 characters
Try these features:
- • Paste complete codes - they'll auto-fill
- • Use arrow keys to navigate between inputs
- • Backspace deletes and moves to previous input
- • Enter moves to next input field
Generated Code
<Root
onChange={setOtp}
>
<Label>Enter Code</Label>
<div className="flex gap-1">
{[...Array(6)].map((_, i) => (
<Input
key={i}
length={1}
className={"min-w-12 px-3 py-2 border border-gray-300 dark:border-gray-700 rounded focus:ring-2 focus:ring-blue-500 dark:bg-gray-800 dark:text-white"
/>
))}
</div>
</Root>Want to improve this page? Create a Pull Request