nextui.dev
Home
Library
Docs
Pricing
Components26
AI & agents5
  • AI chat inputPro
  • Agent task checklistPro
  • Agent thinking
  • Thinking indicator
  • Prompt deckNew
Forms & inputs7
  • Input with label
  • Input with icon and button
  • Settings switches
  • Password with strength meter
  • One-time code input
  • WaitlistNew
  • File dropzonePro
Cards5
  • Style marquee cardPro
  • Folder card
  • Celebration cardPro
  • Smart PDF stackNew
  • Waitlist pass
Buttons, badges & avatars5
  • Buttons with icons
  • QR scan badge
  • Avatar group
  • Rolling price badge
  • Avatars with status
Feedback & display4
  • Alert banners
  • FAQ accordion
  • Keyboard shortcuts
  • Empty state
Blocks11
Hero4
  • Animated pill heroPro
  • Integrations grid hero
  • Waitlist heroNew
  • Orbit chat heroNew
Features & pricing3
  • Usage cardPro
  • Three-tier pricing
  • Feature with board
Testimonials & team3
  • Testimonial cards
  • Single quote
  • Team carousel
Sign-in1
  • Sign-in cardPro
Motion2
Effects2
  • Text revealPro
  • Sound ringNew
Themes9
  • Default
  • Ember
  • Ocean
  • Forest
  • Grape
  • Rose
  • Amber
  • Clay
  • Brutal
nextui.dev

nextui components, blocks and themes you install with one command.

Product

  • Components
  • Blocks
  • Motion
  • Themes
  • Pricing

Resources

  • Docs
  • Roadmap
  • GitHub

Legal

  • License
  • Privacy
  • Terms
  • Refunds

nextUI

[ 200 OK ] · nextUI

© 2026 NEXTUI.DEV. All rights reserved.

ComponentsForms & inputsOne-time code input

One-time code input

Six-digit OTP input with paste, backspace and arrow-key support.

Copy prompt
MCP

Installation

Runs as is, no setup needed. Want a shorter command like @nextui/input-04? See short names.

$pnpm dlx shadcn@latest add https://tinistudio.vercel.app/r/input-04.json

Related

All components

Input with label

Email input with a label and helper text.

Input with icon and button

Newsletter-style input with a leading icon and submit button.

Settings switches

Notification settings list with switches.

npx shadcn@latest add https://tinistudio.vercel.app/r/input-04.json
components/nextui/input-04.tsx
"use client";

import { useRef, useState } from "react";
import { Label } from "@/components/ui/label";

const LENGTH = 6;

export default function Input04() {
  const [digits, setDigits] = useState<string[]>(Array(LENGTH).fill(""));
  const refs = useRef<(HTMLInputElement | null)[]>([]);

  function update(index: number, value: string) {
    const chars = value.replace(/\D/g, "").split("");
    if (!chars.length) return;
    const next = [...digits];
    chars.slice(0, LENGTH - index).forEach((c, i) => (next[index + i] = c));
    setDigits(next);
    refs.current[Math.min(index + chars.length, LENGTH - 1)]?.focus();
  }

  function onKeyDown(index: number, event: React.KeyboardEvent<HTMLInputElement>) {
    if (event.key === "Backspace") {
      event.preventDefault();
      const next = [...digits];
      if (next[index]) next[index] = "";
      else if (index > 0) {
        next[index - 1] = "";
        refs.current[index - 1]?.focus();
      }
      setDigits(next);
    }
    if (event.key === "ArrowLeft") refs.current[index - 1]?.focus();
    if (event.key === "ArrowRight") refs.current[index + 1]?.focus();
  }

  const complete = digits.every(Boolean);

  return (
    <div className="space-y-3 text-center">
      <Label className="justify-center">Enter the 6-digit code</Label>
      <div className="flex items-center gap-2">
        {digits.map((digit, i) => (
          <div key={i} className="contents">
            {i === LENGTH / 2 && <span className="text-muted-foreground">–</span>}
            <input
              ref={(el) => {
                refs.current[i] = el;
              }}
              value={digit}
              inputMode="numeric"
              autoComplete={i === 0 ? "one-time-code" : "off"}
              aria-label={`Digit ${i + 1}`}
              onChange={(e) => update(i, e.target.value)}
              onKeyDown={(e) => onKeyDown(i, e)}
              onFocus={(e) => e.target.select()}
              className="size-11 rounded-lg border border-input bg-transparent text-center text-lg font-medium tabular-nums shadow-xs outline-none transition-[box-shadow,border-color] focus:border-ring focus:ring-[3px] focus:ring-ring/50"
            />
          </div>
        ))}
      </div>
      <p className="text-xs text-muted-foreground">
        {complete ? "Verifying…" : "Didn’t get it? "}
        {!complete && <button className="font-medium text-foreground underline underline-offset-2">Resend code</button>}
      </p>
    </div>
  );
}
Sign in