OtpInput
SMS orqali kelgan bir martalik kodni kiritish: katakchalar, joylash, avtoto'ldirish va qayta yuborish taymeri.
+998 90 *** ** 67 ga yuborildi. Kod: 123456
'use client';
import { Field, OtpInput, toast } from '@akhatmirzo/ui';
import { useState } from 'react';
const CORRECT = '123456';
export default function OtpInputVerify() {
const [code, setCode] = useState('');
const [status, setStatus] = useState<'idle' | 'error' | 'ok'>('idle');
return (
<div className="flex flex-col gap-2">
<Field
label="Tasdiqlash kodi"
description={
status === 'ok' ? 'Kod tasdiqlandi' : `+998 90 *** ** 67 ga yuborildi. Kod: ${CORRECT}`
}
error={status === 'error' ? "Kod noto'g'ri. Qayta urinib ko'ring." : undefined}
>
<OtpInput
groupSize={3}
value={code}
disabled={status === 'ok'}
onValueChange={(value) => {
setCode(value);
if (status === 'error') setStatus('idle');
}}
onComplete={(value) => setStatus(value === CORRECT ? 'ok' : 'error')}
/>
</Field>
<OtpInput.ResendTimer
onResend={() => {
setCode('');
setStatus('idle');
toast('Yangi kod yuborildi');
}}
/>
</div>
);
}
Import
import { OtpInput, ResendTimer } from '@akhatmirzo/ui';ResendTimer — OtpInput.ResendTimer sifatida ham mavjud, alohida import qilish shart emas.
Qachon ishlatish
- Telefon yoki email tasdiqlash, ikki bosqichli kirish — SMS yoki ilovadan kelgan 4–8 xonali kod uchun.
- Kod to'lishi bilan tekshiring:
onCompleteoxirgi belgi kiritilganda chaqiriladi — "Tasdiqlash" tugmasi shart emas. - Xatoni matn bilan ayting:
invalidkatakchalarni qizil qiladi va silkitadi, lekin sababini Field ningerrorprop'ida yozing ("Kod noto'g'ri"). - Qayta yuborishni taymer bilan bering —
ResendTimerfoydalanuvchini SMS kelishini kutishga undaydi va serverni ortiqcha so'rovlardan saqlaydi. - Parol yoki PIN saqlash uchun emas — belgilar ochiq ko'rinadi.
Tasdiqlash oqimi
Yuqoridagi misolda to'g'ri kod — 123456. Noto'g'ri kod kiritilsa, invalid yoqiladi:
katakchalar qizil bo'ladi va guruh yengil silkinadi. Foydalanuvchi qayta yoza boshlaganda xatoni
olib tashlang. Kod tasdiqlangach disabled qilib qo'yish mumkin.
import { Field, OtpInput } from '@akhatmirzo/ui';
import { useState } from 'react';
async function verifyCode(code: string) {
const res = await fetch('/api/verify', { method: 'POST', body: JSON.stringify({ code }) });
return res.ok;
}
export function VerifyForm() {
const [code, setCode] = useState('');
const [error, setError] = useState(false);
return (
<Field label="Tasdiqlash kodi" error={error ? "Kod noto'g'ri" : undefined}>
<OtpInput
value={code}
onValueChange={(v) => {
setCode(v);
setError(false);
}}
onComplete={async (v) => setError(!(await verifyCode(v)))}
/>
</Field>
);
}Joylash va SMS'dan to'ldirish
Butun kodni istalgan katakka joylash (Ctrl+V) mumkin — hamma katakcha to'ladi. Birinchi
katakchada autocomplete="one-time-code" bor: iOS va Android SMS'dagi kodni klaviatura ustida
taklif qiladi.
Uzunlik, tur va guruhlash
length — katakchalar soni (standart 6). type="alphanumeric" harflarni ham qabul qiladi
(standart — faqat raqam). groupSize katakchalarni guruhlarga ajratadi: 3 → 123 – 456.
'use client';
import { OtpInput } from '@akhatmirzo/ui';
import { useState } from 'react';
export default function OtpInputLength() {
const [promo, setPromo] = useState('');
return (
<div className="flex flex-col items-start gap-5">
<OtpInput length={4} aria-label="4 xonali PIN" />
<OtpInput length={6} groupSize={2} aria-label="Juft guruhli kod" />
<div className="flex flex-col gap-2">
<OtpInput
type="alphanumeric"
groupSize={3}
aria-label="Harfli kod"
value={promo}
onValueChange={setPromo}
/>
<span className="text-sm text-text-muted">Qiymat: {promo || '—'}</span>
</div>
</div>
);
}
Holatlar
invalid — qizil chegara va silkinish (prefers-reduced-motion yoqilgan bo'lsa silkinmaydi).
disabled — katakchalar o'chirilgan.
'use client';
import { OtpInput } from '@akhatmirzo/ui';
export default function OtpInputStates() {
return (
<div className="flex flex-col items-start gap-5">
<OtpInput invalid defaultValue="482913" groupSize={3} aria-label="Xato kod" />
<OtpInput disabled defaultValue="12" groupSize={3} aria-label="O'chirilgan" />
</div>
);
}
ResendTimer
"Kodni qayta yuborish (0:59)" — taymer tugaguncha bosilmaydi. onResend Promise qaytarsa, u
tugaguncha ham bosib bo'lmaydi; keyin taymer qaytadan boshlanadi. Taymer komponent paydo bo'lishi
bilan boshlanadi — kod allaqachon yuborilgan deb hisoblanadi.
'use client';
import { OtpInput, toast } from '@akhatmirzo/ui';
const sendSms = () =>
new Promise<void>((resolve) => {
setTimeout(() => {
toast('SMS qayta yuborildi');
resolve();
}, 800);
});
export default function OtpResendTimer() {
return (
<div className="flex flex-col items-start gap-3">
<OtpInput.ResendTimer seconds={5} onResend={() => toast('Kod qayta yuborildi')} />
<OtpInput.ResendTimer
seconds={3}
labels={{ resend: 'SMS ni qayta olish' }}
onResend={sendSms}
/>
</div>
);
}
Props
OtpInput
Qolgan <div> atributlarini (className, aria-label, data-* ...) va ref ni qabul qiladi
(ildiz — katakchalar guruhi).
| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
length | number | 6 | Katakchalar soni |
type | 'numeric' | 'alphanumeric' | 'numeric' | Faqat raqam yoki harf va raqam |
value | string | — | Kod (boshqariladigan) |
defaultValue | string | — | |
onValueChange | (value: string) => void | — | |
onComplete | (code: string) => void | — | Oxirgi belgi kiritilganda |
invalid | boolean | — | Xato: qizil + silkinish (Field ichida error bo'lsa avtomatik) |
disabled | boolean | — | |
groupSize | number | — | Guruhlash: 3 → 123 – 456 |
name | string | — | Forma uchun yashirin maydon nomi |
autoFocus | boolean | — | Birinchi katakchaga fokus |
labels | OtpInputLabels | — | { cell?: (index, length) => string; group?: string } |
ResendTimer
Qolgan <button> atributlarini qabul qiladi.
| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
seconds | number | 60 | Kutish vaqti, soniya |
onResend | () => unknown | — | Bosilganda; Promise qaytarsa — tugaguncha bosib bo'lmaydi |
labels | { resend?: string } | { resend: 'Kodni qayta yuborish' } | |
disabled | boolean | — | Taymerdan qat'i nazar bosilmaydi |
Data atributlari
| Atribut | Element | Qiymat |
|---|---|---|
data-invalid | OtpInput | xato bo'lganda mavjud |
data-disabled | OtpInput | disabled bo'lganda mavjud |
data-complete | OtpInput | barcha katakchalar to'lganda |
data-state | ResendTimer | waiting · ready |
Klaviatura
| Tugma | Harakat |
|---|---|
| Belgi | Katakchani to'ldiradi, fokus keyingisiga o'tadi |
Backspace | Belgini o'chiradi; katakcha bo'sh bo'lsa — oldingisiga qaytadi |
Delete | Joriy katakchadagi belgini o'chiradi |
← → | Katakchalar bo'ylab yurish |
Home / End | Birinchi / birinchi bo'sh katakcha |
Bo'sh joydan keyingi katakchaga sakrab bo'lmaydi — fokus birinchi bo'sh katakchaga o'tadi.
Accessibility
- Guruh —
role="group".Fieldichida label orqali (aria-labelledby), tashqarisida "Tasdiqlash kodi" nomi bilan (labels.group) o'qiladi. - Har bir katakcha — alohida
<input>o'z nomi bilan: "1-raqam", "2-raqam" ... Boshqa tildalabels.cellbilan o'zgartiring:cell: (i, n) => 'Digit ' + (i + 1) + ' of ' + n. aria-invalid,aria-describedby,aria-requiredFielddan har bir katakchaga uzatiladi — xato matni qaysi katakchada bo'lmasin o'qiladi.- Mobil klaviatura:
numericturidainputMode="numeric". - Harakat sezgirligi: silkinish
prefers-reduced-motion: reduceda o'chadi. - ResendTimer kutish paytida
aria-disabled— fokusda qoladi, lekin bosilmaydi; taymer matni tugma nomining bir qismi.