Input OTP
StabilnySegmentowane pole na kody jednorazowe, PIN-y i kody odzyskiwania — z obsługą wklejania, autouzupełniania z SMS-ów i menedżerów haseł.
Instalacja
$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/input-otp.jsonUżycie
import {
InputOTP,
InputOTPGroup,
InputOTPSeparator,
InputOTPSlot,
} from "@/components/ui/input-otp"<InputOTP maxLength={6}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>Input OTP jest zbudowany na input-otp: sloty to tylko obraz jednego prawdziwego pola, które leży pod spodem. Dlatego działają wklejanie, autouzupełnianie z SMS-ów, menedżery haseł, cofanie zmian i czytniki ekranu — do wypełnienia jest jedno pole, a nie sześć.
Przykłady
Tylko cyfry
Przekaż pattern, żeby odrzucać niepasujące znaki już podczas pisania. REGEXP_ONLY_DIGITS pasuje do PIN-ów i kodów z SMS-ów, a domyślny inputMode="numeric" wyświetla na telefonach klawiaturę numeryczną. Wzorce są reeksportowane z @/components/ui/input-otp; podobnie jak samego komponentu, używaj ich w komponentach klienckich.
Litery i symbole są pomijane podczas wpisywania.
Litery i cyfry
W kodach odzyskiwania dopuść litery wzorcem REGEXP_ONLY_DIGITS_AND_CHARS i przełącz inputMode na text, żeby dało się je wpisać z klawiatury telefonu. pasteTransformer czyści wklejane wartości — tutaj usuwa myślniki i zamienia litery na wielkie.
Wklej kod, np. 7F2K-9QXA — myślniki zostaną usunięte.
Tryb kontrolowany z automatycznym wysłaniem
Kontroluj wartość przez value i onChange, a weryfikuj ją w onComplete, który wywołuje się, gdy wszystkie sloty są wypełnione. Na czas weryfikacji wyłącz pole, po nieudanej próbie zachowaj to, co ktoś wpisał, i napisz, dokąd wysłano kod.
Wysłaliśmy go na adres ada@prfct.dev.
Stan błędu
Ustaw aria-invalid na InputOTP, a wszystkie sloty zmienią kolor na czerwony — nie trzeba oznaczać ich pojedynczo. Wyjaśnij problem w FieldError powiązanym przez aria-describedby.
Wytyczne
Kiedy używać
- Kody o stałej długości, które ktoś przepisuje z innego miejsca: kody uwierzytelniania dwuskładnikowego, kody weryfikacyjne z e-maili, PIN-y, kody odzyskiwania.
Kiedy nie używać
- Hasła i wszystko o zmiennej długości — użyj komponentu Input z
type="password". - Kody dłuższe niż mniej więcej 8 znaków — łatwiej wypełnić pojedyncze pole z czytelną wskazówką co do formatu.
Dziel długie kody
Pamięć krótkotrwała mieści naraz trzy, cztery znaki. Podziel kody sześciocyfrowe na dwie grupy po trzy, a ośmioznakowe na dwie grupy po cztery za pomocą InputOTPSeparator — i zachowaj taki sam podział jak w e-mailu lub SMS-ie, który dostarcza kod.
Wybaczaj błędy
Wysyłaj kod automatycznie po wypełnieniu pola, ale nigdy nie zostawiaj ludzi bez wyjścia: po nieudanej próbie zachowaj to, co wpisali, pozwól poprawić dowolny slot i zamiast ślepego zaułka zaproponuj Wyślij kod ponownie z widocznym czasem oczekiwania.
Dostępność
- Jedno pole. Czytniki ekranu ogłaszają jedno pole tekstowe i odczytują całą wartość; w kolejności tabulacji pole zajmuje jedno miejsce, a nie po jednym na każdy slot.
- Podpisz pole. Nadaj
InputOTPid, do którego odwoła sięFieldLabel, alboaria-label, np. Kod weryfikacyjny. - Autouzupełnianie.
autoComplete="one-time-code"jest ustawione domyślnie, więc iOS i Android podpowiadają kody z SMS-ów i e-maili. - Menedżery haseł. Przy
pushPasswordManagerStrategy="increase-width"(wartość domyślna) pole niewidocznie się poszerza, żeby ikony menedżerów haseł nie zasłaniały ostatniego slotu. - Kontrast. Obramowania slotów używają tokenu
inputo kontraście 3:1; aktywny slot dostaje dodatkowo poświatę fokusu w kolorze marki.
| Klawisz | Działanie |
|---|---|
Tab | Przenosi fokus do pola. Kursor trafia do pierwszego pustego slotu. |
0–9 / A–Z | Wypełnia aktywny slot i przechodzi do następnego. Znaki niepasujące do pattern są ignorowane. |
Backspace | Usuwa poprzedni znak. |
←→ | Przesuwa kursor między slotami. |
CtrlV⌘V | Wkleja kod i rozkłada go na sloty. |
Dokumentacja API
InputOTP
Renderuje kontener i jedno ukryte pole <input>. Przyjmuje wszystkie natywne propsy pola input oraz opcje biblioteki input-otp.
InputOTPGroup
Renderuje <div>, który łączy swoje sloty w jeden obramowany segment.
InputOTPSlot
Renderuje komórkę na jeden znak. Przyjmuje wszystkie propsy div.
InputOTPSeparator
Renderuje <div role="separator"> z kreską między grupami.