Interactive demo of OTP input field
/**
* OTP Field Demo - Interactive examples of OTP input fields
*/
import { Form, FormBuilder } from '@saastro/forms';
import { FormProvider } from '@/components/FormProvider';
import { TooltipProvider } from '@/components/ui/tooltip';
const config = FormBuilder.create('otp-demo')
.layout('manual')
.columns(12)
.addField('verificationCode', (f) =>
f
.type('otp')
.label('Verification Code')
.helperText('Enter the 6-digit code sent to your email')
.required('Verification code is required')
.columns({ default: 12 }),
)
.addStep('main', ['verificationCode'])
.build();
export default function OtpDemo() {
const handleSubmit = (data: Record<string, unknown>) => {
console.log('Form submitted:', data);
alert('Form submitted! Check console for data.');
};
return (
<TooltipProvider>
<FormProvider>
<Form config={config} onSubmit={handleSubmit} className="space-y-4" />
</FormProvider>
</TooltipProvider>
);
} Overview
The OTP (One-Time Password) field provides a series of input boxes for entering verification codes. It’s commonly used for 2FA, phone verification, and email confirmation flows.
Usage
Basic OTP Input
import { FormBuilder } from '@saastro/forms';
const config = FormBuilder.create('verification')
.addField('code', (f) =>
f
.type('otp')
.label('Verification Code')
.helperText('Enter the 6-digit code sent to your email')
.required('Verification code is required'),
)
.addStep('main', ['code'])
.build();
With Custom Length
The default OTP length is 6 digits. You can configure this via the component registry.
JSON Configuration
{
"type": "otp",
"label": "Verification Code",
"helperText": "Enter the 6-digit code sent to your phone",
"schema": { "required": true }
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'otp' | - | Field type (required) |
label | string | - | Label text |
helperText | string | - | Help text below input |
columns | Partial<Record<Breakpoint, number>> | - | Grid columns by breakpoint |
disabled | boolean | function | ConditionGroup | false | Disable the field |
hidden | boolean | function | ConditionGroup | Responsive | false | Hide the field |
Validation
Required Code
.addField('verificationCode', (f) =>
f.type('otp')
.label('Enter Code')
.required('Please enter the verification code')
)
With Pattern Validation
.addField('pin', (f) =>
f.type('otp')
.label('PIN')
.required()
.regex('^[0-9]{6}$', 'PIN must be 6 digits')
)
Features
- Auto-focus: Automatically focuses the first empty box
- Auto-advance: Moves to next box after input
- Paste support: Handles pasted codes correctly
- Backspace handling: Moves back on delete
Use Cases
- Email verification: Confirm email ownership
- Phone verification: SMS code entry
- Two-factor authentication: TOTP codes
- Payment confirmation: Transaction PINs
Styling
Custom Classes
.addField('code', (f) =>
f.type('otp')
.label('Verification Code')
.required()
.classNames({
wrapper: 'bg-muted/30 p-6 rounded-lg text-center',
input: 'border-2 border-primary/20',
label: 'text-lg font-semibold',
helper: 'text-muted-foreground text-sm',
error: 'text-destructive text-sm',
})
)
Responsive Layout
.addField('pin', (f) =>
f.type('otp')
.label('PIN')
.columns({ default: 12, md: 6 })
)
JSON Styling
{
"type": "otp",
"label": "Verification Code",
"wrapper_className": "bg-muted/30 p-6 rounded-lg text-center",
"input_className": "border-2 border-primary/20",
"label_className": "text-lg font-semibold",
"columns": { "default": 12, "md": 6 }
}
Accessibility
- Built on input-otp library
- Keyboard navigation between boxes
- Screen reader support
- Focus visible states
- Proper ARIA labels