OTPField
A slot-based input component for one-time passwords, verification codes, 2FA tokens, and SMS confirmations. Supports numeric, alphanumeric, and alpha modes with keyboard navigation, paste handling, and mobile SMS autofill. Works standalone or with DashForm integration.
Quick Start
Copy & Paste
For verification codes—OTP, 2FA, SMS codes, and security tokens
import { OTPField } from '@dashforge/ui';
<OTPField name="otp" length={6} />Examples
Common OTPField patterns and configurations
Basic Numeric
Standard 6-digit OTP for verification codes
<OTPField name="otp" length={6} />Short 4-Digit
4-digit PIN code entry
<OTPField name="pin" length={4} />Alphanumeric Mode
Accept letters and numbers for complex codes
<OTPField
name="token"
length={6}
mode="alphanumeric"
/>Alpha Only
Letter-only verification codes
<OTPField
name="code"
length={4}
mode="alpha"
/>With Label
Display a label above the OTP slots
<OTPField
name="verification"
length={6}
label="Enter verification code"
/>Error State
Show validation errors
Invalid code. Please try again.
<OTPField
name="invalid"
length={6}
error
helperText="Invalid code. Please try again."
/>Controlled
Manage state externally with value/onChange
Current value: (empty)
const [value, setValue] = useState('');
<OTPField
name="controlled"
length={6}
value={value}
onChange={setValue}
/>Completion Callback
Fire callback when all slots are filled
Fill all slots to trigger callback
const [completed, setCompleted] = useState('');
<OTPField
name="complete"
length={6}
onComplete={setCompleted}
/>Dashforge Capabilities
Progressive adoption from controlled components to reactive forms
Use OTPField as a controlled component, integrate with React Hook Form, or leverage reactive capabilities. Choose the adoption level that fits your workflow.
Controlled
Available Now
Works as a standard React controlled component with value and onChange. No proprietary lock-in—use familiar patterns for OTP entry.
Standard value and onChange props (string-based)
Integrate with any state management solution
onComplete callback for submission triggers
const [otp, setOtp] = useState('');
<OTPField
name="otp"
length={6}
value={otp}
onChange={setOtp}
onComplete={(value) => submitCode(value)}
/>React Hook Form Ready
Integration-Friendly
Integrates with React Hook Form via DashForm. Automatic validation, error handling, and touch tracking for OTP fields.
Works with RHF through DashFormBridge
Automatic validation and error gating
Touch state managed automatically on blur
<DashForm>
<OTPField
name="otp"
length={6}
rules={{
required: 'Verification code is required',
minLength: {
value: 6,
message: 'Code must be 6 digits',
},
}}
/>
</DashForm>Reactive Visibility
Available Now
Conditional rendering via visibleWhen. Show OTP field only when needed based on form state, like after phone number entry.
Conditional rendering via visibleWhen
Engine evaluates the predicate reactively
Perfect for multi-step verification flows
<OTPField
name="otp"
length={6}
visibleWhen={(engine) =>
engine.getNode('phoneNumber')?.value?.length === 10
}
/>API Reference
Complete props and type definitions
Explicit vs Auto-Bound Props: When inside DashForm, OTPField receives value, error, helperText, onChange, and onBlur automatically through field binding. Explicit props always take precedence over form-provided values.
| Prop | Type | Default | Description |
|---|---|---|---|
| name | string | - | Field name for form integration (required) |
| length | number | 6 | Number of OTP slots to render |
| mode | 'numeric' | 'alphanumeric' | 'alpha' | 'numeric' | Character entry mode. numeric: 0-9 only. alphanumeric: 0-9, a-z, A-Z. alpha: a-z, A-Z only. |
| value | string | - | Controlled value of the OTP field (complete string, e.g., "123456") |
| onChange | (value: string) => void | - | Callback fired when the value changes. Receives the complete OTP string. |
| onComplete | (value: string) => void | - | Callback fired when all slots are filled. Useful for auto-submit on completion. |
| autoFocus | boolean | false | Auto-focus first slot on mount |
| label | ReactNode | - | Label text displayed above the OTP slots |
| error | boolean | false | If true, displays error state. Explicit error prop overrides form-provided error state. When inside DashForm without explicit prop, error is gated (shows only when touched OR submitted). |
| helperText | ReactNode | - | Helper text displayed below slots. Explicit helperText prop overrides form-provided validation error message. When inside DashForm, validation errors display as helperText (gated by touched/submitted state). |
| disabled | boolean | false | If true, the OTP field is disabled |
| required | boolean | false | If true, displays required indicator in label |
| fullWidth | boolean | false | If true, the container takes up the full width |
| rules | ValidationRules | - | Validation rules for DashForm integration. Format follows React Hook Form rules contract. Only used when inside DashForm—ignored in standalone mode. |
| visibleWhen | (engine: Engine) => boolean | - | Component-level conditional rendering predicate. Receives engine instance with access to all field state via getNode(name). When false, component renders null. Re-evaluates on dependency changes. Only works inside DashForm (requires engine). |
| access | AccessRequirement | - | RBAC access control configuration. Controls field visibility and interaction based on user permissions. Fields can be hidden, disabled, or readonly when users lack access. |
Under the hood
How OTPField behaves and why it works this way
Form integration
Automatically binds to form state inside DashForm. Single onChange handler with string value. Works standalone with controlled value/onChange props when outside DashForm.
Behavior model
Single accessible input with visual slot representation. Keyboard navigation (arrow keys, backspace) and paste handling built-in. Mobile SMS autofill via autoComplete="one-time-code". Errors gated by Form Closure v1 (touch + submit).
Architecture
Built on slot-based UI primitive with single input for accessibility. Supports numeric, alphanumeric, and alpha modes. Fully typed with TypeScript. Caret management for seamless UX.