nori-ui

InputOTP

Segmented one-time-code input with auto-advance, backspace backtrack, and paste-to-fill. Works cross-platform.

3.2 kBgzipped

At a glance

  • Renders length (default 6) individual text cells in a row.
  • Auto-advances focus to the next cell on character entry.
  • Backspace on an empty cell moves focus to the previous cell.
  • Paste of a full code distributes characters across all cells.
  • onComplete fires once all cells are filled.
  • pattern="numeric" (default) or pattern="alphanumeric".
  • Field.Control-compatible: forwards id, aria-labelledby, aria-describedby, aria-invalid.

Preview

Direction:

Usage

import { useState } from 'react';
import { InputOTP } from '@nori-ui/core';
 
export function OTPForm() {
    const [code, setCode] = useState('');
 
    return (
        <InputOTP
            value={code}
            onChange={setCode}
            onComplete={(value) => console.log('Submit:', value)}
            length={6}
        />
    );
}

With Field

import { Field, InputOTP } from '@nori-ui/core';
 
export function OTPField() {
    return (
        <Field>
            <Field.Label>Verification code</Field.Label>
            <Field.Control>
                <InputOTP length={6} />
            </Field.Control>
            <Field.Description>Enter the 6-digit code from your authenticator app.</Field.Description>
        </Field>
    );
}

Alphanumeric

<InputOTP
    value={code}
    onChange={setCode}
    length={8}
    pattern="alphanumeric"
/>

Platform notes

Web: Each cell is an <input> element. The component handles onKeyDown for arrow navigation, backspace, and character entry. Paste is captured on the container div via onPaste.

Native: Each cell is an RN TextInput. Backspace is detected via onKeyPress. Paste is handled by detecting multi-character onChangeText input.

Additional props

  • disabled — prevents all input, dims the cells, and forwards aria-disabled.
  • placeholder — single character shown inside each empty cell as a hint (e.g., "·"). Defaults to no placeholder.
  • autoFocus — focuses the first cell on mount.
  • aria-label — accessible label for the control when no visible label is present (e.g., when used outside a <Field>).

Props

PropTypeDefaultDescription
aria-describedbystringaria-describedby for Field.Control wiring.
aria-invalidboolean | "true" | "false"aria-invalid for Field.Control wiring.
aria-labelstringOne-time codearia-label override. @defaultValue 'One-time code'
aria-labelledbystringaria-labelledby for Field.Control wiring.
autoFocusbooleanfalseAuto-focus the first cell on mount.
classNamestring
disabledbooleanfalseWhether the input is disabled.
idstringa11y / form id forwarded to the first cell.
lengthnumber6Number of OTP cells. @defaultValue 6
namestringForm field name forwarded to hidden input (web).
onChange(value: string) => voidCalled with the full value string on any change.
onComplete(value: string) => voidCalled once the code reaches `length` characters.
patternenumnumericInput character set validation. @defaultValue 'numeric'
placeholderstring·Placeholder shown in empty cells. @defaultValue '·'
testIDstring
valuestringCurrent value (string of digits/chars, length ≤ `length`).

On this page

Preview theme