Skip to content

Commit

Permalink
feat: add UI config defaults, better back navigation to auth UI (#827)
Browse files Browse the repository at this point in the history
  • Loading branch information
bswags authored and moldy530 committed Jul 17, 2024
1 parent d7180c3 commit 0902810
Show file tree
Hide file tree
Showing 16 changed files with 117 additions and 99 deletions.
10 changes: 2 additions & 8 deletions account-kit/react/src/components/auth/card/add-passkey.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useAddPasskey } from "../../../hooks/useAddPasskey.js";
import { useUiConfig } from "../../../hooks/useUiConfig.js";
import { AddPasskeyIllustration } from "../../../icons/illustrations/add-passkey.js";
import {
PasskeyShieldIllustration,
Expand All @@ -25,7 +24,6 @@ const BENEFITS = [

// eslint-disable-next-line jsdoc/require-jsdoc
export const AddPasskey = () => {
const { illustrationStyle } = useUiConfig();
const { setAuthStep } = useAuthContext();
const { addPasskey, isAddingPasskey } = useAddPasskey({
onSuccess: () => {
Expand All @@ -36,11 +34,7 @@ export const AddPasskey = () => {
return (
<div className="flex flex-col gap-5 items-center">
<div className="flex flex-col items-center justify-center h-12 w-12">
<AddPasskeyIllustration
illustrationStyle={illustrationStyle ?? "flat"}
height="48"
width="48"
/>
<AddPasskeyIllustration height="48" width="48" />
</div>

<h3 className="font-semibold text-lg">{ls.addPasskey.title}</h3>
Expand All @@ -49,7 +43,7 @@ export const AddPasskey = () => {
{BENEFITS.map(({ title, icon: Icon, description }) => (
<div key={title} className="flex gap-2">
<div className="h-5 w-5 flex items-center justify-center">
<Icon illustrationStyle={illustrationStyle ?? "flat"} />
<Icon />
</div>
<div className="flex flex-col">
<p className="font-semibold text-sm">{title}</p>
Expand Down
24 changes: 17 additions & 7 deletions account-kit/react/src/components/auth/card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Navigation } from "../../navigation.js";
import { Notification } from "../../notification.js";
import { useAuthContext } from "../context.js";
import { Step } from "./steps.js";
import { useSigner } from "../../../hooks/useSigner.js";

export type AuthCardProps = {
className?: string;
Expand Down Expand Up @@ -41,35 +42,44 @@ export const AuthCardContent = ({
const { status, isAuthenticating } = useSignerStatus();
const { authStep, setAuthStep } = useAuthContext();

const signer = useSigner();
const error = useAuthError();

const contentRef = useRef<HTMLDivElement>(null);
const { height } = useElementHeight(contentRef);

const { auth } = useUiConfig();
const hideError = auth?.hideError;
const onAuthSuccess = auth?.onAuthSuccess;
const didGoBack = useRef(false);

const {
auth: { hideError, onAuthSuccess },
} = useUiConfig();

// TODO: Finalize the steps that allow going back
const canGoBack = useMemo(() => {
return ["email_verify"].includes(authStep.type);
return ["email_verify", "passkey_verify"].includes(authStep.type);
}, [authStep]);

const onBack = useCallback(() => {
switch (authStep.type) {
case "email_verify":
case "passkey_verify":
signer?.disconnect(); // Terminate any inflight authentication
didGoBack.current = true;
setAuthStep({ type: "initial" });
break;
default:
console.warn("Unhandled back action for auth step", authStep);
}
}, [authStep, setAuthStep]);
}, [authStep, setAuthStep, signer]);

useLayoutEffect(() => {
if (authStep.type === "complete") {
didGoBack.current = false;
closeAuthModal();
onAuthSuccess?.();
} else if (isAuthenticating && authStep.type === "initial") {
} else if (authStep.type !== "initial") {
didGoBack.current = false;
} else if (!didGoBack.current && isAuthenticating) {
// Auth step must be initial
const urlParams = new URLSearchParams(window.location.search);

setAuthStep({
Expand Down
9 changes: 1 addition & 8 deletions account-kit/react/src/components/auth/card/loading/email.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { useAuthContext, type AuthStep } from "../../context.js";
import { Spinner } from "../../../../icons/spinner.js";
import { ls } from "../../../../strings.js";
import { EmailIllustration } from "../../../../icons/illustrations/email.js";
import { useUiConfig } from "../../../../hooks/useUiConfig.js";

interface LoadingEmailProps {
context: Extract<AuthStep, { type: "email_verify" }>;
Expand All @@ -18,7 +17,6 @@ export const LoadingEmail = ({ context }: LoadingEmailProps) => {
// yup, re-sent and resent. I'm not fixing it
const [emailResent, setEmailResent] = useState(false);

const { illustrationStyle } = useUiConfig();
const { setAuthStep } = useAuthContext();
const { authenticate } = useAuthenticate({
onSuccess: () => {
Expand All @@ -38,12 +36,7 @@ export const LoadingEmail = ({ context }: LoadingEmailProps) => {
return (
<div className="flex flex-col gap-5 items-center">
<div className="flex flex-col items-center justify-center h-12 w-12">
<EmailIllustration
illustrationStyle={illustrationStyle ?? "flat"}
height="48"
width="48"
className="animate-pulse"
/>
<EmailIllustration height="48" width="48" className="animate-pulse" />
</div>

<h3 className="font-semibold text-lg">{ls.loadingEmail.title}</h3>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@ import { ls } from "../../../../strings.js";
import { LoadingPasskey } from "../../../../icons/passkey.js";
import { Button } from "../../../button.js";
import { PoweredBy } from "../../../poweredby.js";
import { useUiConfig } from "../../../../hooks/useUiConfig.js";

// eslint-disable-next-line jsdoc/require-jsdoc
export const LoadingPasskeyAuth = () => {
const { illustrationStyle } = useUiConfig();

return (
<div className="flex flex-col gap-5 items-center">
<div className="flex flex-col items-center justify-center">
<LoadingPasskey illustrationStyle={illustrationStyle ?? "flat"} />
<LoadingPasskey />
</div>

<h3 className="font-semibold text-lg">{ls.loadingPasskey.title}</h3>
Expand Down
8 changes: 3 additions & 5 deletions account-kit/react/src/components/auth/card/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@ import { useUiConfig } from "../../../hooks/useUiConfig.js";

// eslint-disable-next-line jsdoc/require-jsdoc
export const MainAuthContent = () => {
const { auth } = useUiConfig();

const header = auth?.header ?? null;
const sections = auth?.sections;
const showSignInText = auth?.showSignInText ?? false;
const {
auth: { header, sections, showSignInText },
} = useUiConfig();

return (
<>
Expand Down
9 changes: 1 addition & 8 deletions account-kit/react/src/components/auth/card/passkey-added.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import { useUiConfig } from "../../../hooks/useUiConfig.js";
import { AddedPasskeyIllustration } from "../../../icons/illustrations/added-passkey.js";
import { PoweredBy } from "../../poweredby.js";

// eslint-disable-next-line jsdoc/require-jsdoc
export function PasskeyAdded() {
const { illustrationStyle } = useUiConfig();

return (
<div className="flex flex-col gap-5 items-center">
<div className="flex flex-col items-center justify-center h-12 w-12">
<AddedPasskeyIllustration
illustrationStyle={illustrationStyle ?? "flat"}
height="48"
width="48"
/>
<AddedPasskeyIllustration height="48" width="48" />
</div>
<h3 className="font-semibold text-lg">Passkey added!</h3>
<p className="text-fg-secondary text-sm text-center">
Expand Down
20 changes: 20 additions & 0 deletions account-kit/react/src/createConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,26 @@ export type AlchemyAccountsConfigWithUI = AlchemyAccountsConfig & {
* an additional argument, the configuration object for the Auth Components UI
* (the modal and AuthCard).
*
* @example
* ```ts
* import { sepolia } from "@account-kit/infra"
* import { createConfig } from "@account-kit/react"
*
* const uiConfig = {
* illustrationStyle: "linear",
* auth: {
* sections: [[{ type: "email" }], [{ type: "passkey" }]],
* addPasskeyOnSignup: true,
* },
* }
*
* const config = createConfig({
* rpcUrl: "/api/rpc",
* chain: sepolia,
* ssr: true,
* }, uiConfig)
* ```
*
* @param {CreateConfigProps} props for creating an alchemy account config
* @param {AlchemyAccountsUIConfig} ui the configuration to use for the Auth Components UI
* @returns an alchemy account config object containing the core and client store, as well as the UI config
Expand Down
16 changes: 15 additions & 1 deletion account-kit/react/src/hooks/useUiConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,28 @@

import { useAlchemyAccountContext } from "../context.js";
import { MissingUiConfigError } from "../errors.js";
import type { AlchemyAccountsUIConfig } from "../types.js";

export const useUiConfig = () => {
const { ui } = useAlchemyAccountContext();
if (ui == null) {
throw new MissingUiConfigError("useUiConfig");
}

// We set some defaults here
return {
...ui.config,
};
illustrationStyle: ui.config.illustrationStyle ?? "flat",
auth: {
...ui.config.auth,
addPasskeyOnSignup: ui.config.auth?.addPasskeyOnSignup ?? false,
header: ui.config.auth?.header ?? null,
hideError: ui.config.auth?.hideError ?? false,
sections: ui.config.auth?.sections ?? [
[{ type: "email" }],
[{ type: "passkey" }],
],
showSignInText: ui.config.auth?.showSignInText ?? true,
},
} satisfies AlchemyAccountsUIConfig;
};
15 changes: 8 additions & 7 deletions account-kit/react/src/icons/illustrations/add-passkey.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { type SVGProps } from "react";
import type { IllustrationProps } from "./types.js";
import { useUiConfig } from "../../hooks/useUiConfig.js";

// eslint-disable-next-line jsdoc/require-jsdoc
export const AddPasskeyIllustration = ({
className,
illustrationStyle: style,
...props
}: IllustrationProps) => {
}: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => {
const { illustrationStyle } = useUiConfig();

return (
<>
{style === "outline" && (
{illustrationStyle === "outline" && (
<>
<AddPasskeyOutlineLight
className={`dark:hidden text-fg-accent-brand ${className ?? ""}`}
Expand All @@ -23,7 +24,7 @@ export const AddPasskeyIllustration = ({
/>
</>
)}
{style === "linear" && (
{illustrationStyle === "linear" && (
<>
<AddPasskeyLinearLight
className={`dark:hidden text-fg-accent-brand ${className ?? ""}`}
Expand All @@ -37,7 +38,7 @@ export const AddPasskeyIllustration = ({
/>
</>
)}
{style === "filled" && (
{illustrationStyle === "filled" && (
<>
<AddPasskeyFilledLight
className={`dark:hidden text-fg-accent-brand ${className ?? ""}`}
Expand All @@ -51,7 +52,7 @@ export const AddPasskeyIllustration = ({
/>
</>
)}
{style === "flat" && (
{illustrationStyle === "flat" && (
<>
<AddPasskeyFlatLight
className={`dark:hidden text-fg-accent-brand ${className ?? ""}`}
Expand Down
15 changes: 8 additions & 7 deletions account-kit/react/src/icons/illustrations/added-passkey.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { type SVGProps } from "react";
import type { IllustrationProps } from "./types.js";
import { useUiConfig } from "../../hooks/useUiConfig.js";

// eslint-disable-next-line jsdoc/require-jsdoc
export const AddedPasskeyIllustration = ({
className,
illustrationStyle: style,
...props
}: IllustrationProps) => {
}: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => {
const { illustrationStyle } = useUiConfig();

return (
<>
{style === "outline" && (
{illustrationStyle === "outline" && (
<>
<AddedPasskeyOutlineLight
className={`dark:hidden text-fg-accent-brand ${className ?? ""}`}
Expand All @@ -23,7 +24,7 @@ export const AddedPasskeyIllustration = ({
/>
</>
)}
{style === "linear" && (
{illustrationStyle === "linear" && (
<>
<AddedPasskeyLinearLight
className={`dark:hidden text-fg-accent-brand ${className ?? ""}`}
Expand All @@ -37,7 +38,7 @@ export const AddedPasskeyIllustration = ({
/>
</>
)}
{style === "filled" && (
{illustrationStyle === "filled" && (
<>
<AddedPasskeyFilledLight
className={`dark:hidden text-fg-accent-brand ${className ?? ""}`}
Expand All @@ -51,7 +52,7 @@ export const AddedPasskeyIllustration = ({
/>
</>
)}
{style === "flat" && (
{illustrationStyle === "flat" && (
<>
<AddedPasskeyFlatLight
className={`dark:hidden text-fg-accent-brand ${className ?? ""}`}
Expand Down
15 changes: 8 additions & 7 deletions account-kit/react/src/icons/illustrations/email.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { type SVGProps } from "react";
import type { IllustrationProps } from "./types.js";
import { useUiConfig } from "../../hooks/useUiConfig.js";

// eslint-disable-next-line jsdoc/require-jsdoc
export const EmailIllustration = ({
className,
illustrationStyle: style,
...props
}: IllustrationProps) => {
}: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => {
const { illustrationStyle } = useUiConfig();

return (
<>
{style === "outline" && (
{illustrationStyle === "outline" && (
<>
<EmailOutlineLight
className={`dark:hidden text-fg-accent-brand ${className ?? ""}`}
Expand All @@ -23,7 +24,7 @@ export const EmailIllustration = ({
/>
</>
)}
{style === "linear" && (
{illustrationStyle === "linear" && (
<>
<EmailLinearLight
className={`dark:hidden text-fg-accent-brand ${className ?? ""}`}
Expand All @@ -37,7 +38,7 @@ export const EmailIllustration = ({
/>
</>
)}
{style === "filled" && (
{illustrationStyle === "filled" && (
<>
<EmailFilledLight
className={`dark:hidden text-fg-accent-brand ${className ?? ""}`}
Expand All @@ -51,7 +52,7 @@ export const EmailIllustration = ({
/>
</>
)}
{style === "flat" && (
{illustrationStyle === "flat" && (
<>
<EmailFlatLight
className={`dark:hidden text-fg-accent-brand ${className ?? ""}`}
Expand Down
Loading

0 comments on commit 0902810

Please sign in to comment.