From a61b0fc1d7c22bf233700f7d56c44a5e642ab21a Mon Sep 17 00:00:00 2001 From: Caleb Briancesco Date: Tue, 17 Dec 2024 13:13:45 -0600 Subject: [PATCH 01/10] fix: updating styles for otp input field when focussed --- account-kit/react/src/components/otp-input/otp-input.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account-kit/react/src/components/otp-input/otp-input.tsx b/account-kit/react/src/components/otp-input/otp-input.tsx index b1297af972..11377bec28 100644 --- a/account-kit/react/src/components/otp-input/otp-input.tsx +++ b/account-kit/react/src/components/otp-input/otp-input.tsx @@ -140,7 +140,7 @@ export const OTPInput: React.FC = ({
{initialOTPValue.map((_, i) => ( (refs.current[i] = el)} From c819c8b82890b1e8ba8e226072777e8d7042024f Mon Sep 17 00:00:00 2001 From: Caleb Briancesco Date: Wed, 18 Dec 2024 09:34:37 -0600 Subject: [PATCH 02/10] fix: keeping otp input in view while the code is validated --- .../react/src/components/auth/card/index.tsx | 1 - .../src/components/auth/card/loading/otp.tsx | 100 ++++++++---------- .../react/src/components/auth/card/steps.tsx | 4 +- .../react/src/components/auth/context.ts | 6 -- .../src/components/auth/sections/Footer.tsx | 1 - .../src/components/otp-input/otp-input.tsx | 4 +- 6 files changed, 49 insertions(+), 67 deletions(-) diff --git a/account-kit/react/src/components/auth/card/index.tsx b/account-kit/react/src/components/auth/card/index.tsx index 260259ad86..2fbc949874 100644 --- a/account-kit/react/src/components/auth/card/index.tsx +++ b/account-kit/react/src/components/auth/card/index.tsx @@ -90,7 +90,6 @@ export const AuthCardContent = ({ case "passkey_verify": case "passkey_create": case "oauth_completing": - case "otp_completing": disconnect(config); // Terminate any inflight authentication didGoBack.current = true; setAuthStep({ type: "initial" }); diff --git a/account-kit/react/src/components/auth/card/loading/otp.tsx b/account-kit/react/src/components/auth/card/loading/otp.tsx index 542da7c2db..969aa9af71 100644 --- a/account-kit/react/src/components/auth/card/loading/otp.tsx +++ b/account-kit/react/src/components/auth/card/loading/otp.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useState } from "react"; import { EmailIllustration } from "../../../../icons/illustrations/email.js"; import { ls } from "../../../../strings.js"; import { @@ -14,14 +14,15 @@ import { useSignerStatus } from "../../../../hooks/useSignerStatus.js"; export const LoadingOtp = () => { const { isConnected } = useSignerStatus(); - const { authStep, setAuthStep } = useAuthContext("otp_verify"); + const { authStep } = useAuthContext("otp_verify"); const [otpCode, setOtpCode] = useState(initialOTPValue); - const [errorText, setErrorText] = useState( - getUserErrorMessage(authStep.error) - ); - const resetOTP = () => { + const [errorText, setErrorText] = useState(authStep.error?.message || ""); + const [isDisabled, setIsDisabled] = useState(false); + const { setAuthStep } = useAuthContext(); + const resetOTP = (errorText = "") => { setOtpCode(initialOTPValue); - setErrorText(""); + setErrorText(errorText); + setIsDisabled(false); }; const { authenticate } = useAuthenticate({ onError: (error: any) => { @@ -36,26 +37,11 @@ export const LoadingOtp = () => { }, }); - useEffect(() => { - if (isOTPCodeType(otpCode)) { - setAuthStep({ - type: "otp_completing", - email: authStep.email, - otp: otpCode.join(""), - }); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [otpCode]); - const setValue = (otpCode: OTPCodeType) => { setOtpCode(otpCode); if (isOTPCodeType(otpCode)) { + setIsDisabled(true); const otp = otpCode.join(""); - setAuthStep({ - type: "otp_completing", - email: authStep.email, - otp, - }); authenticate({ type: "otp", otpCode: otp }); } }; @@ -80,6 +66,7 @@ export const LoadingOtp = () => { {authStep.email}

{ ); }; -export const CompletingOtp = () => { - return ( -
-
- -
-

- {ls.completingOtp.title} -

-

- {ls.completingOtp.body} -

-
- ); -}; +// export const CompletingOtp = () => { +// const { isConnected } = useSignerStatus(); +// const { setAuthStep, authStep } = useAuthContext("otp_completing"); +// const { authenticate } = useAuthenticate({ +// onError: (error: any) => { +// console.error(error); +// const { email } = authStep; +// setAuthStep({ type: "otp_verify", email, error }); +// }, +// onSuccess: () => { +// if (isConnected && authStep.createPasskeyAfter) { +// setAuthStep({ type: "passkey_create" }); +// } else if (isConnected) { +// setAuthStep({ type: "complete" }); +// } +// }, +// }); -function getUserErrorMessage(error: Error | undefined): string { - if (!error) { - return ""; - } - // Errors from Alchemy have a JSON message. - try { - const message = JSON.parse(error.message).error; - if (message === "invalid OTP code") { - return ls.error.otp.invalid; - } - return message; - } catch (e) { - // Ignore - } - return error.message; -} +// useEffect(() => { +// authenticate({ type: "otp", otpCode: authStep.otp }); +// // eslint-disable-next-line react-hooks/exhaustive-deps +// }, []); + +// return ( +//
+//
+// +//
+//

+// {ls.completingOtp.title} +//

+//

+// {ls.completingOtp.body} +//

+//
+// ); +// }; diff --git a/account-kit/react/src/components/auth/card/steps.tsx b/account-kit/react/src/components/auth/card/steps.tsx index a6a9eae177..ff74b36a6f 100644 --- a/account-kit/react/src/components/auth/card/steps.tsx +++ b/account-kit/react/src/components/auth/card/steps.tsx @@ -6,7 +6,7 @@ import { CompletingOAuth } from "./loading/oauth.js"; import { LoadingPasskeyAuth } from "./loading/passkey.js"; import { MainAuthContent } from "./main.js"; import { PasskeyAdded } from "./passkey-added.js"; -import { CompletingOtp, LoadingOtp } from "./loading/otp.js"; +import { LoadingOtp } from "./loading/otp.js"; export const Step = () => { const { authStep } = useAuthContext(); @@ -21,8 +21,6 @@ export const Step = () => { return ; case "oauth_completing": return ; - case "otp_completing": - return ; case "passkey_create": return ; case "passkey_create_success": diff --git a/account-kit/react/src/components/auth/context.ts b/account-kit/react/src/components/auth/context.ts index 61827a9712..61e27847f1 100644 --- a/account-kit/react/src/components/auth/context.ts +++ b/account-kit/react/src/components/auth/context.ts @@ -16,12 +16,6 @@ export type AuthStep = config: Extract; error?: Error; } - | { - type: "otp_completing"; - email: string; - otp: string; - error?: Error; - } | { type: "initial"; error?: Error } | { type: "complete" } | { type: "eoa_connect"; connector: Connector; error?: Error } diff --git a/account-kit/react/src/components/auth/sections/Footer.tsx b/account-kit/react/src/components/auth/sections/Footer.tsx index 40ae4781b3..302a30b428 100644 --- a/account-kit/react/src/components/auth/sections/Footer.tsx +++ b/account-kit/react/src/components/auth/sections/Footer.tsx @@ -23,7 +23,6 @@ const RenderFooterText = ({ authStep }: FooterProps) => { case "oauth_completing": return ; case "email_completing": - case "otp_completing": case "passkey_create_success": case "eoa_connect": case "pick_eoa": diff --git a/account-kit/react/src/components/otp-input/otp-input.tsx b/account-kit/react/src/components/otp-input/otp-input.tsx index 11377bec28..fe56075cd2 100644 --- a/account-kit/react/src/components/otp-input/otp-input.tsx +++ b/account-kit/react/src/components/otp-input/otp-input.tsx @@ -7,8 +7,8 @@ const OTP_LENGTH = 6; type OTPInputProps = { errorText?: string; value: OTPCodeType; - setValue: (otp: OTPCodeType) => void; - setErrorText: (error: string) => void; + setValue: (otpCode: OTPCodeType) => void; + setErrorText: React.Dispatch>; disabled?: boolean; handleReset: () => void; className?: string; From 57d2b6c542baca545275490cba58990ea12c1753 Mon Sep 17 00:00:00 2001 From: Caleb Briancesco Date: Wed, 18 Dec 2024 10:31:25 -0600 Subject: [PATCH 03/10] fix: removing un-used component --- .../src/components/auth/card/loading/otp.tsx | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/account-kit/react/src/components/auth/card/loading/otp.tsx b/account-kit/react/src/components/auth/card/loading/otp.tsx index 969aa9af71..c33505f689 100644 --- a/account-kit/react/src/components/auth/card/loading/otp.tsx +++ b/account-kit/react/src/components/auth/card/loading/otp.tsx @@ -76,41 +76,3 @@ export const LoadingOtp = () => {
); }; - -// export const CompletingOtp = () => { -// const { isConnected } = useSignerStatus(); -// const { setAuthStep, authStep } = useAuthContext("otp_completing"); -// const { authenticate } = useAuthenticate({ -// onError: (error: any) => { -// console.error(error); -// const { email } = authStep; -// setAuthStep({ type: "otp_verify", email, error }); -// }, -// onSuccess: () => { -// if (isConnected && authStep.createPasskeyAfter) { -// setAuthStep({ type: "passkey_create" }); -// } else if (isConnected) { -// setAuthStep({ type: "complete" }); -// } -// }, -// }); - -// useEffect(() => { -// authenticate({ type: "otp", otpCode: authStep.otp }); -// // eslint-disable-next-line react-hooks/exhaustive-deps -// }, []); - -// return ( -//
-//
-// -//
-//

-// {ls.completingOtp.title} -//

-//

-// {ls.completingOtp.body} -//

-//
-// ); -// }; From 4e9460866013389537f24a1c7eb801ecebe45740 Mon Sep 17 00:00:00 2001 From: Caleb Briancesco Date: Thu, 19 Dec 2024 13:17:19 -0600 Subject: [PATCH 04/10] fix: make input disable when code is verified --- account-kit/react/src/components/otp-input/otp-input.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account-kit/react/src/components/otp-input/otp-input.tsx b/account-kit/react/src/components/otp-input/otp-input.tsx index fe56075cd2..c8e49bb6ae 100644 --- a/account-kit/react/src/components/otp-input/otp-input.tsx +++ b/account-kit/react/src/components/otp-input/otp-input.tsx @@ -158,7 +158,7 @@ export const OTPInput: React.FC = ({ onInput={focusNextElement} onKeyDown={handleKeydown} key={i} - disabled={disabled} + disabled={disabled || isVerified} value={value[i]} aria-invalid={!!errorText} /> From b00b3d4ee0cc1d7db40f18247fce9ee881fc5edf Mon Sep 17 00:00:00 2001 From: Caleb Briancesco Date: Thu, 19 Dec 2024 13:50:48 -0600 Subject: [PATCH 05/10] fix: fixing unit tests with added color --- account-kit/react/src/tailwind/utils.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/account-kit/react/src/tailwind/utils.test.ts b/account-kit/react/src/tailwind/utils.test.ts index faa0f38296..322cfcb8cc 100644 --- a/account-kit/react/src/tailwind/utils.test.ts +++ b/account-kit/react/src/tailwind/utils.test.ts @@ -91,6 +91,10 @@ describe("tailwind utils test", () => { "dark": "#E2E8F0", "light": "#475569", }, + "fg-success": { + + "dark": "#86EFAC", + + "light": "#16A34A", + + }, "fg-tertiary": { "dark": "#94A3B8", "light": "#94A3B8", From 099952d823b214dcc17e2dc46714abe61066ab30 Mon Sep 17 00:00:00 2001 From: Caleb Briancesco Date: Thu, 19 Dec 2024 13:58:42 -0600 Subject: [PATCH 06/10] fix: fixing unit tests with added color --- account-kit/react/src/tailwind/utils.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/account-kit/react/src/tailwind/utils.test.ts b/account-kit/react/src/tailwind/utils.test.ts index 322cfcb8cc..321b0eac1c 100644 --- a/account-kit/react/src/tailwind/utils.test.ts +++ b/account-kit/react/src/tailwind/utils.test.ts @@ -92,9 +92,9 @@ describe("tailwind utils test", () => { "light": "#475569", }, "fg-success": { - + "dark": "#86EFAC", - + "light": "#16A34A", - + }, + "dark": "#86EFAC", + "light": "#16A34A", + }, "fg-tertiary": { "dark": "#94A3B8", "light": "#94A3B8", From c4cc6a33f6d6e5fc309b6e039074615c19d3c69a Mon Sep 17 00:00:00 2001 From: Caleb Briancesco Date: Fri, 20 Dec 2024 12:03:22 -0600 Subject: [PATCH 07/10] fix: updating styles and flow of otp auth --- .../auth/card/footer/email-not-reveived.tsx | 29 ++++++++++-- .../src/components/auth/card/loading/otp.tsx | 46 +++++++++++++++---- .../react/src/components/auth/context.ts | 13 +++++- .../src/components/otp-input/otp-input.tsx | 16 +++++-- account-kit/react/src/strings.ts | 2 + 5 files changed, 88 insertions(+), 18 deletions(-) diff --git a/account-kit/react/src/components/auth/card/footer/email-not-reveived.tsx b/account-kit/react/src/components/auth/card/footer/email-not-reveived.tsx index 18d62fa577..2bcae57487 100644 --- a/account-kit/react/src/components/auth/card/footer/email-not-reveived.tsx +++ b/account-kit/react/src/components/auth/card/footer/email-not-reveived.tsx @@ -1,7 +1,11 @@ -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { useAuthenticate } from "../../../../hooks/useAuthenticate.js"; import { ls } from "../../../../strings.js"; -import { useAuthContext, type AuthStep } from "../../context.js"; +import { + AuthStepStatus, + useAuthContext, + type AuthStep, +} from "../../context.js"; import { Button } from "../../../button.js"; type EmailNotReceivedDisclaimerProps = { @@ -18,6 +22,14 @@ export const EmailNotReceivedDisclaimer = ({ }, }); + const isOTPVerifying = useMemo(() => { + return ( + authStep.type === "otp_verify" && + (authStep.status === AuthStepStatus.verifying || + authStep.status === AuthStepStatus.success) + ); + }, [authStep]); + useEffect(() => { if (emailResent) { // set the text back to "Resend" after 2 seconds @@ -29,13 +41,20 @@ export const EmailNotReceivedDisclaimer = ({ return (
- + {ls.loadingEmail.emailNotReceived}

- {ls.loadingOtp.title} + {titleText}

{ls.loadingOtp.body} @@ -66,13 +76,31 @@ export const LoadingOtp = () => { {authStep.email}

); }; + +function getUserErrorMessage(error: Error | undefined): string { + if (!error) { + return ""; + } + // Errors from Alchemy have a JSON message. + try { + const message = JSON.parse(error.message).error; + if (message === "invalid OTP code") { + return ls.error.otp.invalid; + } + return message; + } catch (e) { + // Ignore + } + return error.message; +} diff --git a/account-kit/react/src/components/auth/context.ts b/account-kit/react/src/components/auth/context.ts index 61e27847f1..e3b14107ee 100644 --- a/account-kit/react/src/components/auth/context.ts +++ b/account-kit/react/src/components/auth/context.ts @@ -4,9 +4,20 @@ import type { Connector } from "@wagmi/core"; import { createContext, useContext } from "react"; import type { AuthType } from "./types"; +export enum AuthStepStatus { + success = "success", + error = "error", + verifying = "verifying", +} + export type AuthStep = | { type: "email_verify"; email: string } - | { type: "otp_verify"; email: string; error?: Error } + | { + type: "otp_verify"; + email: string; + error?: Error; + status?: AuthStepStatus | null; + } | { type: "passkey_verify"; error?: Error } | { type: "passkey_create"; error?: Error } | { type: "passkey_create_success" } diff --git a/account-kit/react/src/components/otp-input/otp-input.tsx b/account-kit/react/src/components/otp-input/otp-input.tsx index c8e49bb6ae..d1e14b4d5d 100644 --- a/account-kit/react/src/components/otp-input/otp-input.tsx +++ b/account-kit/react/src/components/otp-input/otp-input.tsx @@ -12,6 +12,7 @@ type OTPInputProps = { disabled?: boolean; handleReset: () => void; className?: string; + isVerified?: boolean; }; export const isOTPCodeType = (arg: string[]): arg is OTPCodeType => { @@ -30,6 +31,7 @@ export const OTPInput: React.FC = ({ setErrorText, handleReset, className, + isVerified, }) => { const [autoComplete, setAutoComplete] = useState(""); const [activeElement, setActiveElement] = useState(0); @@ -140,9 +142,17 @@ export const OTPInput: React.FC = ({
{initialOTPValue.map((_, i) => ( (refs.current[i] = el)} tabIndex={i + 1} type="text" diff --git a/account-kit/react/src/strings.ts b/account-kit/react/src/strings.ts index a5680833bf..b37469d59d 100644 --- a/account-kit/react/src/strings.ts +++ b/account-kit/react/src/strings.ts @@ -35,6 +35,8 @@ const STRINGS = { body: "We sent a verification code to", notReceived: "Didn't receive code?", resend: "Resend", + verifying: "Verifying...", + verified: "Verified!", }, completingEmail: { body: "Completing login. Please wait a few seconds for this to screen to update.", From 3c1b585be0f13ff7220dfee90be4bd738b63bddf Mon Sep 17 00:00:00 2001 From: Caleb Briancesco Date: Fri, 20 Dec 2024 12:29:42 -0600 Subject: [PATCH 08/10] fix: adding color to theme --- account-kit/react/src/tailwind/theme.ts | 1 + account-kit/react/src/tailwind/types.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/account-kit/react/src/tailwind/theme.ts b/account-kit/react/src/tailwind/theme.ts index d329d20961..7c77e66ec9 100644 --- a/account-kit/react/src/tailwind/theme.ts +++ b/account-kit/react/src/tailwind/theme.ts @@ -26,6 +26,7 @@ export function createDefaultTheme(): AccountKitTheme { "fg-disabled": createColorSet("#CBD5E1", "#475569"), "fg-accent-brand": createColorSet("#E82594", "#FF66CC"), "fg-critical": createColorSet("#B91C1C", "#F87171"), + "fg-success": createColorSet("#16A34A", "#86EFAC"), // surface colors "bg-surface-default": createColorSet("#fff", "#020617"), diff --git a/account-kit/react/src/tailwind/types.ts b/account-kit/react/src/tailwind/types.ts index 0f65307bf1..03b2572d8e 100644 --- a/account-kit/react/src/tailwind/types.ts +++ b/account-kit/react/src/tailwind/types.ts @@ -22,6 +22,7 @@ export interface AccountKitTheme { "fg-disabled": ColorVariantRecord; "fg-accent-brand": ColorVariantRecord; "fg-critical": ColorVariantRecord; + "fg-success": ColorVariantRecord; // surface colors "bg-surface-default": ColorVariantRecord; From 0782fa5e5017ef023c8b943eec22a4cc331754af Mon Sep 17 00:00:00 2001 From: Caleb Briancesco Date: Mon, 13 Jan 2025 10:37:45 -0600 Subject: [PATCH 09/10] fix: adding pr feedback --- .../auth/card/footer/email-not-reveived.tsx | 5 +++-- .../react/src/components/auth/card/loading/otp.tsx | 11 +++++------ account-kit/react/src/components/auth/context.ts | 3 ++- .../react/src/components/otp-input/otp-input.tsx | 11 ++++++----- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/account-kit/react/src/components/auth/card/footer/email-not-reveived.tsx b/account-kit/react/src/components/auth/card/footer/email-not-reveived.tsx index 2bcae57487..841cfc07c5 100644 --- a/account-kit/react/src/components/auth/card/footer/email-not-reveived.tsx +++ b/account-kit/react/src/components/auth/card/footer/email-not-reveived.tsx @@ -51,9 +51,10 @@ export const EmailNotReceivedDisclaimer = ({