@@ -11,6 +11,7 @@ import { FormError } from "~/components/primitives/FormError";
1111import { Header1 } from "~/components/primitives/Headers" ;
1212import { Input } from "~/components/primitives/Input" ;
1313import { InputGroup } from "~/components/primitives/InputGroup" ;
14+ import { InputOTP , InputOTPGroup , InputOTPSlot } from "~/components/primitives/InputOTP" ;
1415import { Paragraph } from "~/components/primitives/Paragraph" ;
1516import { Spinner } from "~/components/primitives/Spinner" ;
1617import { authenticator } from "~/services/auth.server" ;
@@ -101,6 +102,7 @@ export default function LoginMfaPage() {
101102 const { mfaError } = useTypedLoaderData < typeof loader > ( ) ;
102103 const navigate = useNavigation ( ) ;
103104 const [ showRecoveryCode , setShowRecoveryCode ] = useState ( false ) ;
105+ const [ mfaCode , setMfaCode ] = useState ( "" ) ;
104106
105107 const isLoading =
106108 ( navigate . state === "loading" || navigate . state === "submitting" ) &&
@@ -111,7 +113,7 @@ export default function LoginMfaPage() {
111113 return (
112114 < LoginPageLayout >
113115 < Form method = "post" >
114- < div className = "flex flex-col items-center justify-center" >
116+ < div className = "flex max-w-xs flex-col items-center justify-center" >
115117 < Header1 className = "pb-4 text-center font-semibold leading-7 sm:text-2xl md:text-3xl md:leading-8 lg:text-4xl lg:leading-9" >
116118 Multi-factor authentication
117119 </ Header1 >
@@ -164,29 +166,33 @@ export default function LoginMfaPage() {
164166 ) : (
165167 < >
166168 < Paragraph variant = "base" className = "mb-6 text-center" >
167- Open your authenticator app to get your code.
169+ Open your authenticator app to get your code. Then enter it below.
168170 </ Paragraph >
169171 < Fieldset className = "flex w-full flex-col items-center gap-y-2" >
170- < InputGroup >
171- < Input
172- type = "text"
173- name = "mfaCode"
174- spellCheck = { false }
175- placeholder = "6-digit code"
176- variant = "large"
177- required
178- autoFocus
179- maxLength = { 6 }
180- pattern = "[0-9]{6}"
181- />
182- </ InputGroup >
172+ < InputOTP
173+ maxLength = { 6 }
174+ value = { mfaCode }
175+ onChange = { ( value ) => setMfaCode ( value ) }
176+ variant = "large"
177+ fullWidth
178+ >
179+ < InputOTPGroup variant = "large" fullWidth >
180+ < InputOTPSlot index = { 0 } autoFocus variant = "large" fullWidth />
181+ < InputOTPSlot index = { 1 } variant = "large" fullWidth />
182+ < InputOTPSlot index = { 2 } variant = "large" fullWidth />
183+ < InputOTPSlot index = { 3 } variant = "large" fullWidth />
184+ < InputOTPSlot index = { 4 } variant = "large" fullWidth />
185+ < InputOTPSlot index = { 5 } variant = "large" fullWidth />
186+ </ InputOTPGroup >
187+ </ InputOTP >
188+ < input type = "hidden" name = "mfaCode" value = { mfaCode } />
183189
184190 < Button
185191 name = "action"
186192 value = "verify-mfa"
187193 type = "submit"
188194 variant = "primary/large"
189- disabled = { isLoading }
195+ disabled = { isLoading || mfaCode . length !== 6 }
190196 fullWidth
191197 data-action = "verify mfa code"
192198 >
0 commit comments