/v1.0

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}
    />
  );
}