Skip to content

Commit

Permalink
feat: add toggle for code preview mode (#731)
Browse files Browse the repository at this point in the history
* feat: add dev mode toggle

* fix: update switch color
  • Loading branch information
tinaszheng authored and moldy530 committed Jul 17, 2024
1 parent 1e04601 commit 5607645
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 59 deletions.
2 changes: 1 addition & 1 deletion examples/ui-demo/components/ui/switch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const Switch = React.forwardRef<
>(({ className, ...props }, ref) => (
<SwitchPrimitives.Root
className={cn(
"peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
"peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-btn-primary data-[state=unchecked]:bg-input",
className
)}
{...props}
Expand Down
74 changes: 16 additions & 58 deletions examples/ui-demo/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,15 @@

import { Public_Sans, Inter } from "next/font/google";

import {
AuthCard,
AuthType,
DemoSet,
useAuthError,
useAuthModal,
useUser,
} from "@account-kit/react";
// eslint-disable-next-line import/extensions
import { ChevronRight } from "@/src/components/icons/chevron";
import { MailIcon } from "@/src/components/icons/mail";
import { Input, useLogout } from "@account-kit/react";
import { useMemo } from "react";
import { useState } from "react";
import { TopNav } from "../components/topnav/TopNav";
import { Button } from "../components/shared/Button";
import { PhoneIcon } from "lucide-react";
import { ArrowUpRightIcon } from "../components/icons/arrow";
import { Configuration } from "../components/configuration";
import { useConfig } from "./state";
import { CodePreview } from "../components/preview/CodePreview";
import { AuthCardWrapper } from "../components/preview/AuthCardWrapper";
import { CodePreviewSwitch } from "../components/shared/CodePreviewSwitch";

const publicSans = Public_Sans({
subsets: ["latin"],
Expand All @@ -33,18 +23,7 @@ const inter = Inter({
});

export default function Home() {
const { config } = useConfig();

const sections = useMemo<AuthType[][]>(() => {
const output = [];
if (config.auth.showEmail) {
output.push([{ type: "email" as const }]);
}

output.push([{ type: "passkey" as const }]);

return output;
}, [config.auth]);
const [showCode, setShowCode] = useState(false);

return (
<main
Expand Down Expand Up @@ -74,43 +53,22 @@ export default function Home() {
<div className="flex flex-col basis-0 flex-1 bg-white border border-static rounded-lg p-6 overflow-y-scroll">
<Configuration />
</div>
<div
className="flex-[2] basis-0 bg-white border border-static rounded-lg flex flex-col justify-center items-center overflow-auto"
style={{
backgroundImage: "url(/images/grid.png)",
backgroundSize: "100px",
backgroundRepeat: "repeat",
}}
>
<div className="flex flex-col gap-2 w-[368px]">
<div className="modal bg-white shadow-md">
<AuthCard
header={<AuthCardHeader />}
showSignInText
showNavigation
sections={sections}
/>
<div className="flex flex-col flex-[2] basis-0 relative bg-white border border-static rounded-lg">
<div className="absolute top-6 right-6 flex items-center gap-2">
<div className="bg-purple-50 text-[#8B5CF6] px-2 py-1 rounded text-xs font-semibold">
Configuration preview
</div>
<CodePreviewSwitch
checked={showCode}
onCheckedChange={setShowCode}
/>
</div>
{/* Don't unmount when showing code preview so that the auth card retains its state */}
<AuthCardWrapper className={showCode ? "hidden" : ""} />
{showCode && <CodePreview />}
</div>
</div>
</div>
</main>
);
}

function AuthCardHeader() {
const {
config: {
ui: { logoDark, logoLight, theme },
},
} = useConfig();

const logo = theme === "dark" ? logoDark : logoLight;

if (!logo) return null;

return (
<img style={{ height: "60px" }} src={logo.fileSrc} alt={logo.fileName} />
);
}
21 changes: 21 additions & 0 deletions examples/ui-demo/src/components/icons/code.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { SVGProps } from "react";

export const Code = ({
stroke = "currentColor",
...props
}: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
<svg
width="16"
height="16"
viewBox="0 0 14 10"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6.19961 8.8002L7.79961 1.2002M2.99961 7.6002L0.599609 5.2002L2.99961 2.8002M10.9996 2.8002L13.3996 5.2002L10.9996 7.6002"
stroke="#020617"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
60 changes: 60 additions & 0 deletions examples/ui-demo/src/components/preview/AuthCardWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { cn } from "@/lib/utils";
import { useConfig } from "@/src/app/state";
import { AuthCard, AuthType } from "@account-kit/react";
import { useMemo } from "react";

export function AuthCardWrapper({ className }: { className?: string }) {
const { config } = useConfig();

const sections = useMemo<AuthType[][]>(() => {
const output = [];
if (config.auth.showEmail) {
output.push([{ type: "email" as const }]);
}

output.push([{ type: "passkey" as const }]);

return output;
}, [config.auth]);

return (
<div
className={cn(
"flex flex-1 flex-col justify-center items-center overflow-auto",
className
)}
style={{
backgroundImage: "url(/images/grid.png)",
backgroundSize: "100px",
backgroundRepeat: "repeat",
}}
>
<div className="flex flex-col gap-2 w-[368px]">
<div className="modal bg-white shadow-md">
<AuthCard
header={<AuthCardHeader />}
showSignInText
showNavigation
sections={sections}
/>
</div>
</div>
</div>
);
}

function AuthCardHeader() {
const {
config: {
ui: { logoDark, logoLight, theme },
},
} = useConfig();

const logo = theme === "dark" ? logoDark : logoLight;

if (!logo) return null;

return (
<img style={{ height: "60px" }} src={logo.fileSrc} alt={logo.fileName} />
);
}
58 changes: 58 additions & 0 deletions examples/ui-demo/src/components/preview/CodePreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { cn } from "@/lib/utils";
import ExternalLink from "../shared/ExternalLink";

import { Roboto_Mono } from "next/font/google";
const robotoMono = Roboto_Mono({
subsets: ["latin"],
display: "swap",
});

export function CodePreview() {
return (
<div className="flex flex-col gap-6 p-6 overflow-y-auto">
<div className="flex flex-col gap-2">
<div className="font-semibold text-fg-primary text-xl">
Export configuration
</div>
<div className="text-sm text-gray-600">
To get started, simply paste the below code into your environment.
You’ll need to add your Alchemy API key and Gas Policy ID too. Login
to automatically inject the keys into the code below.{" "}
<ExternalLink href="#" className="text-blue-600 font-semibold">
Fully customize CSS here.
</ExternalLink>
</div>
</div>
<div className="flex flex-col gap-4">
<div className="font-semibold text-fg-secondary">Style</div>
<CodeBlock title="tailwind.config.ts" code={styleCode} />
</div>
<div className="flex flex-col gap-4">
<div className="font-semibold text-fg-secondary">Config</div>
<CodeBlock title="src/app/page.tsx" code={styleCode} />
</div>
</div>
);
}

function CodeBlock({ title, code }: { title: string; code: string }) {
return (
<div className="rounded-lg flex flex-col text-sm overflow-hidden">
<div className="px-4 py-3 bg-gray-700 text-white font-medium">
{title}
</div>
<pre
className={cn("px-4 py-6 bg-gray-800 text-white", robotoMono.className)}
>
{code}
</pre>
</div>
);
}

const styleCode = `import { withAccountKitUi } from "@alchemy/aa-alchemy/tailwind";
import type { Config } from "tailwindcss";
const config: Config = <your tailwind config>;
export default withAccountKitUi(config);
`;
32 changes: 32 additions & 0 deletions examples/ui-demo/src/components/shared/CodePreviewSwitch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"use client"

import * as React from "react"
import * as SwitchPrimitives from "@radix-ui/react-switch"

import { cn } from "@/lib/utils"
import { Code } from "../icons/code"

const CodePreviewSwitch = React.forwardRef<
React.ElementRef<typeof SwitchPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
>(({ className, ...props }, ref) => (
<SwitchPrimitives.Root
className={cn(
"peer inline-flex h-[28px] w-[50px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-btn-primary data-[state=unchecked]:bg-input",
className
)}
{...props}
ref={ref}
>
<SwitchPrimitives.Thumb
className={cn(
"flex items-center justify-center pointer-events-none h-[24px] w-[24px] rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-[22px] data-[state=unchecked]:translate-x-0"
)}
>
<Code />
</SwitchPrimitives.Thumb>
</SwitchPrimitives.Root>
))
CodePreviewSwitch.displayName = SwitchPrimitives.Root.displayName

export { CodePreviewSwitch }

0 comments on commit 5607645

Please sign in to comment.