@mshafiqyajid/react-otp-input

v0.1.0 ~20 KB 0 deps react

Headless OTP / verification-code input hook and styled component for React. Smart paste fills all slots. Full keyboard nav. Masking, group separators, label/hint/error states, and SMS autofill via autoComplete=one-time-code.

$ npm install @mshafiqyajid/react-otp-input

Playground #

Verification code

Type or paste to auto-fill

Props
6
TSX
import { OTPInputStyled } from "@mshafiqyajid/react-otp-input/styled";
import "@mshafiqyajid/react-otp-input/styles.css";

<OTPInputStyled
  onComplete={handleComplete}
/>

Install #

npm install @mshafiqyajid/react-otp-input

Quick start #

import { OTPInputStyled } from "@mshafiqyajid/react-otp-input/styled";
import "@mshafiqyajid/react-otp-input/styles.css";

<OTPInputStyled
  length={6}
  tone="primary"
  onComplete={(code) => verify(code)}
  autoFocus
/>

Recipes #

Controlled with verification flow

const [code, setCode] = useState("");
const [status, setStatus] = useState<"idle" | "verifying" | "error">("idle");

<OTPInputStyled
  length={6}
  value={code}
  onChange={(v) => { setCode(v); setStatus("idle"); }}
  onComplete={async (final) => {
    setStatus("verifying");
    try { await verify(final); } catch { setStatus("error"); }
  }}
  error={status === "error" ? "Invalid code" : undefined}
  disabled={status === "verifying"}
/>

Alphanumeric pattern (e.g. license keys)

<OTPInputStyled
  length={8}
  pattern="alphanumeric"
  groupSize={4}
  uppercase
  label="License key"
/>

Masked PIN entry

<OTPInputStyled
  length={4}
  mask
  pattern="numeric"
  label="PIN"
  hint="Hidden for privacy"
/>

API #

OTPInputStyled

PropTypeDefaultDescription
lengthnumber6Number of slots.
valuestringControlled value.
onChange(value: string) => voidFires on change.
onComplete(value: string) => voidFires when all slots filled.
patternnumeric | alphanumeric | any | RegExp | fnnumericAllowed characters.
variantsolid | outline | underlinesolidVisual style.
sizesm | md | lgmdSize.
toneneutral | primary | success | dangerneutralColor theme.
maskbooleanfalseShow maskChar instead of typed char.
groupSizenumberInsert separator after every N slots.
autoFocusbooleanfalseFocus first slot on mount.
labelReactNodeLabel above.
hintReactNodeHelper text below.
errorReactNodeError text — flips tone to danger.
Edit this page on GitHub