# 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: - `onComplete` never fired on typing due to a JS bug (`!string.includes("")` is always false) - Manual focus management across 6 separate `` 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) ```ts 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-border` default, `border-primary` + ring on active, `border-danger` on 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 - `useOtpHandlers` hook (focus, paste, keydown management) - `getInputBorderClass` helper - All 6 individual `` 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.