shadcn.io is not affiliated with official shadcn/ui
One-Time Code Input Form Block for Solid
A six-slot confirmation code in two groups of three with its behaviours in view: paste fills all six and checks at once, a wrong code is marked, counted and cleared, and a resend button waits 30 seconds.
Installation
Overview
Show how a code field behaves, with this one-time code input form for Solid with Ark UI. A compact header sits over a hairline frame with a plus mark on each corner and one row. At the start, the label, a Locked or Open Badge, where the code went, how many attempts remain, and a Resend code Countdown Button that waits 30 seconds after each press. At the end, an Input OTP of six slots in two groups of three. Typing fills the slots in order, Backspace steps back, the arrow keys move across and pasting "428 193", spaces and all, fills all six and checks at once; so does the sixth digit. A wrong code marks every slot invalid, says how many attempts remain, clears the slots and puts focus on the first; after three the field locks until a new code is requested. Open Door 4, the only Shine Button, says what is missing when the code is not complete. It's built from Input OTP, Countdown Button, Badge and Guides. For door and device confirmation, sign-in codes and any short code you ask a person to type.
FAQ
How does pasting a code with spaces work?
The block takes the paste before the field sees it: it keeps only the digits of what was on the clipboard, drops any beyond six and fills the slots, then checks. That makes "428 193", "428-193" and a code copied with a trailing newline all work the same on every version, which a field that validates each paste against its own pattern would refuse. The slots are marked autocomplete="one-time-code" and numeric, so a phone can offer the code from a text message too.
What happens on a wrong code, and why clear the slots?
After a short beat, so you see what you typed, every slot is marked aria-invalid, the line under them says "That code does not match. 2 attempts remain.", the slots are emptied and focus goes to the first, so the next try starts from the start of the field. The foot says the same once in its polite status. After three wrong codes the field stops taking digits, the sentence says why and focus goes to the button, which now reads Request a new code.
Which keys work, and is it the same on every version?
Digits fill and advance, Backspace clears the slot and steps back, the arrow keys, Home and End move between slots, and Enter checks or says what is missing. Each slot is its own input, so a screen reader reads six fields in a group. The slots read left to right even on a right-to-left page, as codes are typed.
How does the Resend code button wait?
Pressing it starts a 30 second count: its label counts down, a fill drains behind it, and it stays focusable but ignores presses until the time is up. It also gives a fresh code: all attempts come back, the slots empty and focus returns to the first one. Nothing is sent in this demo; in your app send the code from the click handler and set the wait from your server's own limit.
What stays local, and how do I connect it for real?
The code is 428193, typed in the file and printed once in the hint, and it is compared in the browser. Nothing is sent, unlocked or stored. In your app post the digits to your server, count attempts there (the page's count is only a courtesy), expire codes after minutes and never reveal the code in the page; keep the status line for the server's answer.
How do I connect it to react-hook-form or TanStack Form?
Hold the six digits as one string in the form. react-hook-form is a React library; use TanStack Form's adapter for your framework and set the field value from the same handler. With TanStack Form, validate the length on change, check the code in onSubmitAsync and call field.setValue("") on a refusal.