One-time code
Collects a one-time code in one cell per character. Supports auto-advance, backspace, and paste.
Preview
In action
When to use
Use it for
- Numeric verification codes from SMS, mail, or an authenticator.
- onComplete to submit as soon as the last cell fills.
Not for
- Alphanumeric codes; the cells strip non-digits.
- Passwords; use Input type="password".
Install
Three ways in. They share one source, so the pixels match whichever you pick.
1. Import the package
npm install @noorddev/vlak-react
// once, next to your app's root
import "@noorddev/vlak-react/css";
import { InputOTP } from "@noorddev/vlak-react";Precompiled React and one stylesheet. No compiler to configure. Per-component imports work too: @noorddev/vlak-react/components/input-otp.
2. Vendor the source
npx @noorddev/vlak-cli add input-otp
The StyleX leaf lands in components/vlak/, for your own compiler to own. See StyleX.
3. Through shadcn
npx shadcn add https://vlak.dev/r/input-otp.json
The same registry item, installed by shadcn's CLI.
CSS only
<link rel="stylesheet" href="node_modules/@noorddev/vlak/css/vlak.css" />
No React. Link vlak.css and use the markup and classes below.
React
import { InputOTP } from "@noorddev/vlak-react";
<InputOTP length={6} aria-label="One-time code" onComplete={(code) => verify(code)} />Props
InputOTP
One cell per character. Auto-advance, backspace, paste.
| Prop | Type | Default | Description |
|---|---|---|---|
length | number | 6 | |
onChange | (code: string) => void | ||
onComplete | (code: string) => void | Called once every cell is filled. | |
aria-label | string | "One-time code" | Defines a string value that labels the current element. |
Also accepts Omit<HTMLAttributes<HTMLDivElement>, "onChange">.
Keyboard
| Keys | Does |
|---|---|
| Type a digit | Fills the cell and moves to the next |
| Backspace | Clears the cell; on an empty cell moves back and clears the previous one |
| Arrow left, Arrow right | Moves between cells |
| Paste | Fills from the current cell onward |
Accessibility
- Renders role="group" named by aria-label ("One-time code" by default); each cell is an <input> named "Digit n".
- inputMode="numeric" and autoComplete="one-time-code" on the first cell let phones offer the code.
- Inside Field, hint and error reach the group and cells through aria-describedby and aria-invalid.
Markup
<div class="rs-otp" role="group" aria-label="One-time code"><input class="rs-otp-cell" maxlength="1" value="8" aria-label="Digit 1" /><input class="rs-otp-cell" maxlength="1" value="2" aria-label="Digit 2" /><input class="rs-otp-cell" maxlength="1" aria-label="Digit 3" /><input class="rs-otp-cell" maxlength="1" aria-label="Digit 4" /></div>
Classes
.rs-otp.rs-otp-cell.rs-otp-cell-invalid