Input OTP

فیلد کد تأیید پیامکی: هر رقم یک خانه، چسباندن کد از پیامک، حرکت خودکار بین خانه‌ها و پاک‌کردن با Backspace. کاربر می‌تواند ۱۲۳۴۵۶ فارسی تایپ کند و مقداری که به سرور می‌رسد همیشه لاتین است.

ری‌اکت ۱۹ و Next.js با پیاده‌سازی دسترس‌پذیری داخلی دیگویو ۳ با Composition API و Reka UISvelte ۵ با runes و Bits UIانگولار با signals و Angular CDK

این کامپوننت فعلاً برای ۱ فریم‌ورک از ۴ فریم‌ورک آماده است.

این نمونه هنوز برای Vue پورت نشده است؛ آنچه می‌بینید نسخهٔ ری‌اکت است.

این نمونه هنوز برای Svelte پورت نشده است؛ آنچه می‌بینید نسخهٔ ری‌اکت است.

این نمونه هنوز برای Angular پورت نشده است؛ آنچه می‌بینید نسخهٔ ری‌اکت است.

نصب

با CLI اختصاصی dig-ui کامپوننت را از رجیستری دیگ نصب کنید؛ وابستگی‌ها و فایل‌ها خودکار اضافه می‌شوند.

نصب سریع با لینک سخت و دیسک مشترکپکیج‌منیجر پیش‌فرض Node.jsYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیج‌منیجر Bun
pnpm dlx dig-ui@latest add https://design-system-tau-green.vercel.app/r/input-otp.json
npx dig-ui@latest add https://design-system-tau-green.vercel.app/r/input-otp.json
yarn dlx dig-ui@latest add https://design-system-tau-green.vercel.app/r/input-otp.json
bunx --bun dig-ui@latest add https://design-system-tau-green.vercel.app/r/input-otp.json

این کامپوننت هنوز برای Vue پورت نشده است.

نسخهٔ ری‌اکت آماده است؛ پورت این فریم‌ورک روی Reka UI در دست کار است.

این کامپوننت هنوز برای Svelte پورت نشده است.

نسخهٔ ری‌اکت آماده است؛ پورت این فریم‌ورک روی Bits UI در دست کار است.

این کامپوننت هنوز برای Angular پورت نشده است.

نسخهٔ ری‌اکت آماده است؛ پورت این فریم‌ورک روی Angular CDK در دست کار است.

استفاده

"use client"

import * as React from "react"
import {
  InputOTP,
  InputOTPGroup,
  InputOTPSlot,
} from "@/components/ui/input-otp"

const [code, setCode] = React.useState("")

<InputOTP value={code} onValueChange={setCode}>
  <InputOTPGroup>
    {[0, 1, 2, 3, 4, 5].map((index) => (
      <InputOTPSlot key={index} index={index} />
    ))}
  </InputOTPGroup>
</InputOTP>

این کامپوننت هنوز برای Vue پورت نشده است.

نسخهٔ ری‌اکت آماده است؛ پورت این فریم‌ورک روی Reka UI در دست کار است.

این کامپوننت هنوز برای Svelte پورت نشده است.

نسخهٔ ری‌اکت آماده است؛ پورت این فریم‌ورک روی Bits UI در دست کار است.

این کامپوننت هنوز برای Angular پورت نشده است.

نسخهٔ ری‌اکت آماده است؛ پورت این فریم‌ورک روی Angular CDK در دست کار است.

ترکیب اجزا

بدون هیچ وابستگی بیرونی است: هر خانه یک input واقعی و مستقل است، نه یک div که ظاهر ورودی را شبیه‌سازی می‌کند. همین یعنی مکان‌نما، انتخاب متن و اتوفیل کد پیامک روی iOS/Android دقیقاً همان رفتار پیش‌فرض مرورگر را دارند، بدون نیاز به شبیه‌سازی دستی. ریشه همیشه dir=ltr می‌گیرد چون کد از چپ به راست خوانده و وارد می‌شود، حتی وسط یک صفحهٔ راست‌به‌چپ. پاک‌سازی پیش‌فرض ارقام فارسی و عربی را به لاتین تبدیل می‌کند و هر نویسهٔ دیگری را دور می‌ریزد؛ اگر کدتان حروف هم دارد، sanitizeValue خودتان را بدهید.

دسترس‌پذیری

  • با autocomplete=one-time-code مرورگر و iOS کد پیامک را پیشنهاد می‌دهند؛ این را از ریشه برندارید.
  • inputMode=numeric صفحه‌کلید عددی موبایل را باز می‌کند.
  • ناوبری بین خانه‌ها با کلیدهای جهت‌دار است و Backspace روی خانهٔ خالی به خانهٔ قبلی برمی‌گردد.
  • برای کل گروه یک Label با htmlFor بگذارید و در حالت خطا invalid را روی Root بدهید تا هر شش خانه با هم قرمز شوند.
  • با autoSubmit فرم به‌محض کامل شدن کد ارسال می‌شود؛ اگر کاربر ممکن است اشتباه تایپ کند، بهتر است دکمهٔ تأیید صریح داشته باشید.

مرجع API

InputOTP

ویژگینوعپیش‌فرضتوضیح
value / onValueChangestring / (value: string) => voidحالت کنترل‌شده؛ مقدار همیشه رشته‌ای از ارقام لاتین است.
defaultValuestringمقدار اولیه در حالت کنترل‌نشده.
sanitizeValue(value: string) => stringتبدیل ارقام فارسی و حذف غیرعددپاک‌سازی ورودی پیش از ثبت؛ برای کدهای حرفی‌عددی بازنویسی کنید.
validationType"alpha" | "numeric" | "alphanumeric" | "none""none"اعتبارسنجی هر نویسه پیش از پذیرفتنش؛ چون خودمان با sanitizeValue پاک‌سازی می‌کنیم روی none است.
type"text" | "password""text"مخفی کردن ارقام واردشده.
variant"separated" | "connected""separated"separated خانه‌های جدا و گِرد با پس‌زمینهٔ خاکستری خنثی است، پرکاربردترین حالت، بدون سایه، برای هرجا از جمله روی Card/Surface. connected آن‌ها را در یک نوار کادردار و سایه‌دار به هم می‌چسباند.
invalidbooleanfalseخطا را روی همهٔ خانه‌ها یک‌جا می‌نشاند؛ نیازی به تکرار aria-invalid روی تک‌تک خانه‌ها نیست.
faDigitsbooleantrueنمایش ارقام به فارسی؛ مقدار ثبت‌شده همیشه لاتین می‌ماند (مثل faDigits در Input). پیش‌فرض روشن است و به کیبورد یا لوکیل کاربر بستگی ندارد؛ برای موارد خاص که کد باید عیناً لاتین دیده شود با faDigits={false} خاموشش کنید.
onComplete(value: string) => voidهر بار همهٔ خانه‌ها پر شوند صدا زده می‌شود، با تایپ، چسباندن یا اتوفیل، صرف‌نظر از autoSubmit.
autoSubmitbooleanfalseارسال خودکار نزدیک‌ترین فرم به‌محض پر شدن همهٔ خانه‌ها.
name / formstringبرای ارسال در فرم؛ کل کد در یک input مخفی قرار می‌گیرد.
disabled / readOnlybooleanfalseقفل کردن ورودی‌ها.

InputOTPSlot

ویژگینوعپیش‌فرضتوضیح
indexnumberجای خانه در ترتیب؛ دادنش از پرش ظاهری بعد از هیدریشن جلوگیری می‌کند.
aria-invalidbooleanبازنویسی دستی خطا برای همین یک خانه؛ برای خطای کل کد از invalid روی Root استفاده کنید.
data-filled"true" | undefinedattribute فقط‌خواندنی؛ وقتی خانه رقم دارد true است، قلاب استایل‌دهی سفارشی با data-[filled=true]:.

InputOTPGroup / InputOTPSeparator

ویژگینوعپیش‌فرضتوضیح
InputOTPGroupReact.ComponentProps<"div">در variant=separated (پیش‌فرض) هر خانه گوشهٔ خودش را دارد و با فاصله می‌نشیند؛ در connected خانه‌ها را می‌چسباند و فقط گوشه‌های اول و آخر منطقی گِرد می‌شوند.
InputOTPSeparatorReact.ComponentProps<"div">خط تیرهٔ بین دو گروه؛ role=separator دارد و خوانده نمی‌شود.

این کامپوننت هنوز برای Vue پورت نشده است.

نسخهٔ ری‌اکت آماده است؛ پورت این فریم‌ورک روی Reka UI در دست کار است.

این کامپوننت هنوز برای Svelte پورت نشده است.

نسخهٔ ری‌اکت آماده است؛ پورت این فریم‌ورک روی Bits UI در دست کار است.

این کامپوننت هنوز برای Angular پورت نشده است.

نسخهٔ ری‌اکت آماده است؛ پورت این فریم‌ورک روی Angular CDK در دست کار است.