AuthVerifyOtp
One-time-code verification page. Renders an InputOTP of N slots and auto-submits when the code is full; routes verification through adapter.verifyOtp({ code, intent }). Optional resend button calls adapter.resendOtp.
Installation
pnpm dlx @hex-core/cli add auth-verify-otpUsage
import { AuthVerifyOtp } from "@/components/ui/auth-verify-otp"Sign-in OTP (mock adapter)
Magic-link or email-OTP sign-in flow with auto-submit when full.
import { AuthVerifyOtp, mockAuthAdapter } from "@hex-core/components";
<AuthVerifyOtp adapter={mockAuthAdapter} intent="sign-in" />MFA challenge
Second-factor TOTP entry with intent='mfa'.
<AuthVerifyOtp adapter={authAdapter} intent="mfa" />API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
adapterrequired | object | — | AuthAdapter implementation. The block calls adapter.verifyOtp({ code, intent }) when the OTP is full and adapter.resendOtp({ intent }) when the resend button is clicked. |
intentrequired | "sign-in" | "verify-email" | "mfa" | — | Reason for the verification. Drives the heading + description copy and is forwarded verbatim to both verifyOtp and resendOtp so consumers can route to the correct backend code. |
length | number | 6 | Total number of digits in the code. Drives both maxLength on the underlying input-otp library and the number of slots rendered. |
resendCooldownSeconds | number | 30 | Seconds the resend button stays disabled after each successful resend. Counter ticks down every second while > 0. |
className | string | — | Additional classes applied to the outer flex wrapper. |
onSuccess | function | — | Called after a successful verification with the adapter's redirect target: (redirect: string | undefined) => void. |
AI Guidance
When to use
Use whenever you need to verify a 6-digit code (or longer) — sign-in via email OTP, post-signup email verification, or TOTP MFA challenge. The intent prop drives both copy and the adapter routing.
When not to use
Don't use for magic-link verification (that lands the user via email click — there's no code to enter). For magic-link wait pages, use auth-verify-email instead.
Common mistakes
- Submitting the form yourself — the block already auto-submits when the code reaches `length`. Don't render an extra submit button.
- Hard-coding length=6 when the backend expects a different number — drive `length` from the same constant the email/SMS template uses.
- Mismatching intent between verifyOtp and resendOtp — the block forwards the same intent to both. If the consumer's adapter routes them differently, that's a bug to fix in the adapter, not the block.
- Showing the resend button when adapter.resendOtp isn't implemented — the block already hides it; don't re-implement that gate.
- Setting resendCooldownSeconds too low (< 10s) — invites accidental double-sends and tripping rate-limit responses.
Accessibility
InputOTP is labeled via aria-label='One-time code' so screen readers know what's being entered. Resend button uses the canonical loading prop (sets aria-busy + disabled). Cooldown countdown is reflected in the visible button label. Errors render in an Alert with role='alert'. The OTP value clears on error so users can re-enter without manually deleting digits.
Related components
Token budget: 1300
Verified against @hex-core/components@1.9.0