OtpInput
Renders a row of single-character input boxes for entering a one-time password or verification code. Automatically advances focus to the next box on input, retreats on Backspace, and fills all boxes when the user pastes a full code. Fires onChange on every keystroke and onComplete when all boxes are filled.
Props
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| onChange | (code: string) => void | Yes | — | Fired on every change with the current concatenated value. |
| length | number | No | 4 | Number of character input boxes. |
| onComplete | (code: string) => void | No | — | Fired when all boxes are filled. |
| autoFocus | boolean | No | false | Focuses the first input on mount. |
| type | 'number' \| 'text' | No | 'number' | Input type. 'number' only allows digit characters. |
| disabled | boolean | No | false | Disables all inputs. |
| error | boolean | No | false | Highlights all inputs with a red border. |
| containerStyle | React.CSSProperties | No | — | Inline styles for the outer container. |
| inputStyle | React.CSSProperties | No | — | Inline styles applied to each individual input box. |
| containerClassName | string | No | — | CSS class name for the container. |
| inputClassName | string | No | — | CSS class name for each input. |
Usage
Basic 6-digit OTP
import OtpInput from '@/components/OtpInput';
export default function Example() {
const handleComplete = (code: string) => {
console.log('OTP entered:', code);
};
return (
<OtpInput
length={6}
onChange={(val) => console.log('Current:', val)}
onComplete={handleComplete}
autoFocus
/>
);
}
With error state
import { useState } from 'react';
import OtpInput from '@/components/OtpInput';
export default function Example() {
const [error, setError] = useState(false);
const handleComplete = (code: string) => {
if (code !== '123456') setError(true);
};
return (
<OtpInput
length={6}
onChange={() => setError(false)}
onComplete={handleComplete}
error={error}
/>
);
}