A polished one-time-password input with animated cells, a pulsing caret, spring-loaded digits, success glow and error shake.
Enter the 6-digit code (try 123456).
pnpm dlx shadcn@latest add https://matos-ui.com/r/otp-input.jsonimport { OtpInput } from '@/components/matos-ui/otp-input'<OtpInput
label="Verification code"
length={6}
onComplete={(code) => verify(code)}
/>Use the OTP Input for short, fixed-length codes: two-factor authentication, email
or SMS verification, and PIN entry. It behaves like a single field — typing,
pasting, autofill (autocomplete="one-time-code") and keyboard navigation all
work out of the box — while rendering one animated cell per character.
Drive the value yourself and react to onComplete to verify the code. Setting
error turns the cells destructive and triggers a subtle shake.
const [value, setValue] = useState('')
const [error, setError] = useState<string>()
<OtpInput
label="Verification code"
value={value}
onChange={setValue}
error={error}
onComplete={(code) => {
if (code !== '123456') setError('Invalid code.')
}}
/>Use groupSize to split the cells with separators (for example XXX-XXX).
<OtpInput length={6} groupSize={3} />Hide the characters behind dots for sensitive PINs.
<OtpInput type="numeric" mask length={4} />Accept letters and numbers for invite or backup codes.
<OtpInput type="alphanumeric" length={8} />chart-2 glow sweeps over the group when every cell is filled.| Prop | Type | Default | Description |
|---|---|---|---|
length | number | 6 | Number of cells / characters. |
value | string | — | Controlled value. |
defaultValue | string | "" | Initial value when uncontrolled. |
onChange | (value: string) => void | — | Called whenever the value changes. |
onComplete | (value: string) => void | — | Called once when all cells are filled. |
type | "numeric" | "alphanumeric" | "text" | "numeric" | Allowed characters and input mode. |
mask | boolean | false | Render dots instead of the typed characters. |
groupSize | number | — | Insert a separator after every N cells. |
size | "sm" | "md" | "lg" | "md" | Cell size. |
variant | "default" | "subtle" | "default" | Visual style of the cells. |
label | ReactNode | — | Field label. |
description | ReactNode | — | Helper text below the field. |
error | ReactNode | — | Error message; marks the field invalid and shakes it. |
invalid | boolean | false | Force the invalid state without a message. |
disabled | boolean | false | Disable the input. |
Also exported: otpInputVariants and the OtpInputProps / OtpInputType types.
type="numeric" for SMS/email codes so mobile keyboards show digits.label (or rely on the built-in aria-label) for screen readers.error / description text, not color alone.Install Matos UI
Choose a package manager and copy one command for every component.