Skip to main content

Overview

One-Time Password Field provides a specialized input component for entering verification codes, typically sent via SMS or email. It breaks the code into individual character inputs for better user experience.

Features

  • Individual character inputs for better visualization
  • Automatic focus management
  • Full keyboard navigation
  • Paste support for complete codes
  • Customizable input validation
  • Works inside forms
  • Accessible by default with proper ARIA attributes

Installation

npm install @radix-ui/react-one-time-password-field

Anatomy

import * as OTPField from '@radix-ui/react-one-time-password-field';

export default () => (
  <OTPField.Root>
    <OTPField.Input />
    <OTPField.HiddenInput />
  </OTPField.Root>
);

API Reference

Root

Contains all the one-time password field parts.
value
string
The controlled value of the OTP field.
defaultValue
string
The value when initially rendered (uncontrolled).
onValueChange
(value: string) => void
Event handler called when the value changes.
onComplete
(value: string) => void
Event handler called when all inputs are filled.
maxLength
number
default:"6"
The maximum number of characters for the OTP.
pattern
string
A regex pattern to validate each character. Examples: [0-9] for digits only, [a-zA-Z0-9] for alphanumeric.
inputType
'text' | 'numeric'
default:"'text'"
The input mode for mobile keyboards.
name
string
The name of the field. Submitted with its owning form as part of a name/value pair.
disabled
boolean
When true, prevents the user from interacting with the field.
required
boolean
When true, indicates that the user must fill the field before submitting the form.
dir
'ltr' | 'rtl'
The reading direction. If omitted, inherits from the parent.
asChild
boolean
default:"false"
Change the default rendered element for the one passed as a child.

Input

A single character input. Render this multiple times based on your maxLength.
index
number
required
The index of this input in the sequence (0-based).
asChild
boolean
default:"false"
Change the default rendered element for the one passed as a child.

HiddenInput

A hidden input that contains the complete value for form submission.

Example

import * as OTPField from '@radix-ui/react-one-time-password-field';
import './styles.css';

export default () => (
  <OTPField.Root className="OTPRoot" maxLength={6}>
    <div style={{ display: 'flex', gap: 8 }}>
      <OTPField.Input className="OTPInput" index={0} />
      <OTPField.Input className="OTPInput" index={1} />
      <OTPField.Input className="OTPInput" index={2} />
      <OTPField.Input className="OTPInput" index={3} />
      <OTPField.Input className="OTPInput" index={4} />
      <OTPField.Input className="OTPInput" index={5} />
    </div>
    <OTPField.HiddenInput />
  </OTPField.Root>
);

Accessibility

The component automatically manages focus and provides proper ARIA labels for screen readers.

Keyboard Interactions

  • ArrowLeft - Moves focus to the previous input.
  • ArrowRight - Moves focus to the next input.
  • Backspace - Deletes the current character and moves focus to the previous input.
  • Delete - Deletes the current character.
  • Paste - Pastes clipboard content and fills multiple inputs if applicable.

Features

  • Automatic focus management between inputs
  • Auto-advances to next input on character entry
  • Auto-moves to previous input on backspace
  • Supports pasting complete codes
  • Properly labeled for screen readers

Build docs developers (and LLMs) love