shadcn.io is an independent project built on shadcn/ui
Six boxes sit blurred beside an eye button. A line under them says Toggle visibility to show/hide the entered code.
Blur the code when it might be read over someone's shoulder. A Password Input fits a password, not a one-time code. In React, Ark UI moves to the next box as you type.
Installation
Anatomy

Usage
<div className="flex flex-col gap-4">
<div className="flex items-center gap-2">
<div className={cn(!showValue && "select-none blur-sm")}>
<InputOTP onValueChange={handleValueChange} value={value}>
<InputOTPGroup>
<InputOTPSlot className="bg-background" index={0} />
<InputOTPSlot className="bg-background" index={1} />
<InputOTPSlot className="bg-background" index={2} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot className="bg-background" index={3} />
<InputOTPSlot className="bg-background" index={4} />
<InputOTPSlot className="bg-background" index={5} />
</InputOTPGroup>
</InputOTP>
</div>
<Button
aria-label={showValue ? "Hide code" : "Show code"}
onClick={handleToggle}
size="icon-md"
type="button"
variant="ghost"
>
{showValue ? (
<EyeOffIcon aria-hidden="true" />
) : (
<EyeIcon aria-hidden="true" />
)}
</Button>
</div>
{/* The rest of the file is under Installation. */}FAQ
How is the code hidden?
The field's wrapper gets blur-sm and select-none while the code is hidden. The digits are still typed normally; they're just unreadable on screen.
How does the eye button work?
Whether the code is shown lives in state. The ghost Button at size icon-md flips it and swaps EyeIcon for EyeOffIcon.
How do screen readers know what the button does?
Its aria-label follows the state: Show code while hidden, Hide code while shown. The icons have aria-hidden.
Can the slots show dots instead?
Yes. Set mask on InputOTP and each slot shows a dot, like a password field; toggle it from the same state as the blur.
API Reference
Input OTP
Sets onValueChange={handleValueChange}, value={value}, index={0}, index={1}, index={2} and index={3}. The rest is on the Input OTP page.
Button
Sets aria-label={showValue ? "Hide code" : "Show code"}, onClick={handleToggle}, size="icon-md", type="button" and variant="ghost". The rest is on the Button page.





