- Added input-otp library to streamline OTP input functionality. - Refactored OtpInput component to utilize InputOTP for improved user experience and mobile SMS autofill. - Enhanced LoginOtpStep and VerificationStep components to handle OTP input errors and clear states effectively. - Updated global styles to include animations for OTP caret, improving visual feedback during input. - Made minor adjustments to LoginForm and OtpStep components for better error handling and user interaction.
2.6 KiB
2.6 KiB
OTP Input Redesign: Replace Custom with shadcn InputOTP
Date: 2026-03-06 Status: Approved
Problem
The custom OtpInput component (components/molecules/OtpInput/OtpInput.tsx) has fundamental issues:
onCompletenever fired on typing due to a JS bug (!string.includes("")is always false)- Manual focus management across 6 separate
<input>elements is fragile - No mobile SMS autofill support
- No password manager detection
- Edge cases around paste, backspace, and focus are hard to maintain
Decision
Replace the custom implementation with input-otp via shadcn/ui's InputOTP component (Approach A).
Architecture
input-otp (npm)
-> components/ui/input-otp.tsx (shadcn primitives)
-> components/molecules/OtpInput/OtpInput.tsx (wrapper, same API)
-> LoginOtpStep, OtpStep, VerificationStep (no changes)
Component API (unchanged)
interface OtpInputProps {
length?: number; // default 6
value: string;
onChange: (value: string) => void;
onComplete?: (value: string) => void;
disabled?: boolean;
error?: string;
autoFocus?: boolean; // default true
}
Visual Design
- Stripe-style grouped layout: two groups of 3 slots separated by a dash
- Slots:
border-borderdefault,border-primary+ ring on active,border-dangeron error bg-card,text-foreground, rounded corners on group edges- Disabled:
opacity-50 cursor-not-allowed - Blinking caret animation
What Changes
| File | Action |
|---|---|
package.json |
Add input-otp dependency |
components/ui/input-otp.tsx |
New — shadcn generated primitives |
components/molecules/OtpInput/OtpInput.tsx |
Rewrite internals, keep API |
LoginOtpStep, OtpStep, VerificationStep |
No changes |
What Gets Deleted
useOtpHandlershook (focus, paste, keydown management)getInputBorderClasshelper- All 6 individual
<input>elements
Error Handling
Consumer-level error handling (already implemented this session) remains unchanged:
- LoginOtpStep: catches errors, clears input, clears error on typing via
onClearError - OtpStep: catches errors, clears input, clears error on typing via
clearOtpError - VerificationStep: syncs machine error to local state, clears input and error on typing
shadcn CLI Note
Generated file imports cn from @/lib/utils. Project has cn at @/shared/utils. Fix the import in the generated file after running the CLI.