Skip to content

Commit

Permalink
feat: prototype the auth modal hook (#638)
Browse files Browse the repository at this point in the history
  • Loading branch information
moldy530 committed May 2, 2024
1 parent 76e961a commit ebed224
Show file tree
Hide file tree
Showing 12 changed files with 196 additions and 101 deletions.
62 changes: 62 additions & 0 deletions examples/ui-demo/src/app/AuthModal.tsx
@@ -0,0 +1,62 @@
import { ReactNode, useCallback, useRef } from "react";

type AuthType =
| {
type: "email";
showButton: boolean;
}
| { type: "passkey" };

type AuthModalProps = {
header?: ReactNode;
// Each section can contain multiple auth types which will be grouped together
// and separated by an OR divider
sections?: AuthType[][];
};

// TODO: move this into aa-alchemy
export const useAuthModal = ({ header = "Sign in" }: AuthModalProps) => {
const ref = useRef<HTMLDialogElement>(null);
const openAuthModal = () => ref.current?.showModal();
const closeAuthModal = () => ref.current?.close();

// TODO: use the sections prop to render the auth types
const AuthModal = useCallback(() => {
return (
<dialog ref={ref} className="modal w-[368px]">
<div className="modal-box flex flex-col items-center gap-5">
<h3 className="font-bold text-lg">{header}</h3>
<div className="flex flex-col gap-2 w-full">
<label className="input">
<input placeholder="Email"></input>
</label>
<button className="btn btn-primary">Continue</button>
</div>
{/* divider */}
<div
className={`flex flex-row gap-3 w-full items-center text-fg-tertiary`}
>
<div className={`h-[1px] bg-static basis-full shrink grow`}></div>
<p>Or</p>
<div className={`h-[1px] bg-static basis-full shrink grow`}></div>
</div>
<div className="flex flex-col w-full">
<button className="btn btn-auth grow">Passkey</button>
</div>
<div className="flex flex-col w-full items-center text-xs gap-3">
<span className="text-fg-tertiary text-center">
By signing in, you agree to the following{" "}
<a className="text-fg-accent-brand cursor-pointer" href="">
End User Terms
</a>
</span>
<span className="text-fg-disabled">powered by INSERT_LOGO</span>
</div>
</div>
<div className="modal-backdrop" onClick={() => closeAuthModal()}></div>
</dialog>
);
}, [header]);

return { openAuthModal, closeAuthModal, AuthModal };
};
113 changes: 65 additions & 48 deletions examples/ui-demo/src/app/page.tsx
Expand Up @@ -2,9 +2,14 @@

import { DemoSet } from "@alchemy/aa-alchemy/react";
import { JSX, SVGProps } from "react";
// eslint-disable-next-line import/extensions
import { useAuthModal } from "./AuthModal";

// TODO: move this into the aa-alchemy package
const MailIcon = ({fill = "#475569", ...props}: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
const MailIcon = ({
fill = "#475569",
...props
}: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={18}
Expand All @@ -21,58 +26,70 @@ const MailIcon = ({fill = "#475569", ...props}: JSX.IntrinsicAttributes & SVGPro
</svg>
);

const ChevronRight = ({ fill = "#475569", ...props }: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={20}
height={20}
fill="none"
{...props}
>
<path
fill="#000"
fillRule="evenodd"
d="M7.058 4.558a.625.625 0 0 1 .884 0l5 5a.625.625 0 0 1 0 .884l-5 5a.625.625 0 1 1-.884-.884L11.616 10 7.058 5.442a.625.625 0 0 1 0-.884Z"
clipRule="evenodd"
/>
</svg>
)
const ChevronRight = ({
fill = "#475569",
...props
}: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={20}
height={20}
fill="none"
{...props}
>
<path
fill="#000"
fillRule="evenodd"
d="M7.058 4.558a.625.625 0 0 1 .884 0l5 5a.625.625 0 0 1 0 .884l-5 5a.625.625 0 1 1-.884-.884L11.616 10 7.058 5.442a.625.625 0 0 1 0-.884Z"
clipRule="evenodd"
/>
</svg>
);

export default function Home() {
const { openAuthModal, AuthModal } = useAuthModal({});

return (
<main className="flex min-h-screen flex-row gap-6 p-24">
<DemoSet>Primary</DemoSet>
<DemoSet type="secondary">Secondary</DemoSet>
<DemoSet type="social">Google</DemoSet>
<div className="flex flex-col gap-4">
<label className="form-controls">
<span className="form-label">Normal Input</span>
<label className="input">
<MailIcon />
<input placeholder="Input"/>
<ChevronRight className="match-input"/>
<>
<main className="flex min-h-screen flex-row gap-6 p-24">
<DemoSet>Primary</DemoSet>
<DemoSet type="secondary">Secondary</DemoSet>
<DemoSet type="social">Google</DemoSet>
<div className="flex flex-col gap-4">
<label className="form-controls">
<span className="form-label">Normal Input</span>
<label className="input">
<MailIcon />
<input placeholder="Input" />
<ChevronRight className="match-input" />
</label>
<span className="form-hint">This is a hint text to help user.</span>
</label>
<span className="form-hint">This is a hint text to help user.</span>
</label>
<label className="form-controls">
<span className="form-label">Disabled Input</span>
<label className="input input-disabled">
<MailIcon />
<input placeholder="Input"/>
<ChevronRight className="match-input"/>
<label className="form-controls">
<span className="form-label">Disabled Input</span>
<label className="input input-disabled">
<MailIcon />
<input placeholder="Input" />
<ChevronRight className="match-input" />
</label>
<span className="form-hint">This is a hint text to help user.</span>
</label>
<span className="form-hint">This is a hint text to help user.</span>
</label>
<label className="form-controls">
<span className="form-label">Error Input</span>
<label className="input input-error">
<MailIcon />
<input placeholder="Input"/>
<ChevronRight className="match-input"/>
<label className="form-controls">
<span className="form-label">Error Input</span>
<label className="input input-error">
<MailIcon />
<input placeholder="Input" />
<ChevronRight className="match-input" />
</label>
<span className="form-hint">This is a hint text to help user.</span>
</label>
<span className="form-hint">This is a hint text to help user.</span>
</label>
</div>
</main>
</div>
<button className="btn btn-primary" onClick={openAuthModal}>
Open Auth Modal
</button>
</main>

<AuthModal />
</>
);
}
13 changes: 7 additions & 6 deletions examples/ui-demo/tailwind.config.ts
Expand Up @@ -6,14 +6,15 @@ const config: Config = withAccountKitUi({
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}"
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {},
plugins: [plugin(({ addComponents }) => {
// use this as a playground to test out new styles and components before moving them
addComponents({
});
})],
plugins: [
plugin(({ addComponents }) => {
// use this as a playground to test out new styles and components before moving them
addComponents({});
}),
],
});

export default config;
8 changes: 4 additions & 4 deletions packages/alchemy/src/tailwind/components/buttons.ts
Expand Up @@ -4,7 +4,7 @@ export const buttonComponents: ComponentDef = {
".btn": {
"@apply p-3 inline-flex h-10 font-semibold": {},
"@apply gap-2": {},
"@apply items-center": {},
"@apply items-center justify-center": {},
"@apply shrink-0": {},
"@apply cursor-pointer": {},
// for w/e reason, using @apply rounded-[8px] doesn't work
Expand All @@ -18,13 +18,13 @@ export const buttonComponents: ComponentDef = {
"@apply active:shadow-none": {},
},
".btn-primary": {
"@apply btn-bg-primary": {},
"@apply bg-btn-primary text-fg-invert": {},
},
".btn-secondary": {
"@apply btn-bg-secondary": {},
"@apply bg-btn-secondary text-fg-primary": {},
},
".btn-auth": {
"@apply btn-bg-social": {},
"@apply bg-btn-social text-fg-primary": {},
"@apply static-border": {},
},
};
5 changes: 2 additions & 3 deletions packages/alchemy/src/tailwind/components/form-controls.ts
@@ -1,18 +1,17 @@
import type { ComponentDef } from "../types.js";
import { getColorVariableName } from "../utils.js";

export const formControlComponents: ComponentDef = {
".form-controls": {
"@apply flex flex-col gap-2": {},
[`@apply text-[var(${getColorVariableName("fg-secondary")})]`]: {},
"@apply text-fg-secondary": {},
".form-label": {
"@apply text-sm font-medium": {},
},
".form-hint": {
"@apply text-xs font-normal": {},
},
".input-error + .form-hint, .input[error] + .form-hint": {
[`@apply text-[var(${getColorVariableName("critical")})]`]: {},
"@apply text-critical": {},
},
},
};
24 changes: 11 additions & 13 deletions packages/alchemy/src/tailwind/components/input.ts
@@ -1,28 +1,26 @@
import type { ComponentDef } from "../types";
import { getColorVariableName } from "../utils.js";

export const inputComponents: ComponentDef = {
".input": {
// container styling
"@apply p-3 inline-flex gap-2 h-10 items-center": {},
"@apply static-border": {},
[`@apply text-[var(${getColorVariableName("fg-primary")})]`]: {},
"@apply text-fg-primary": {},
"&-disabled, &:disabled, &[disabled]": {
"@apply static-border pointer-events-none": {},
[`@apply bg-[var(${getColorVariableName("bg-surface-inset")})]`]: {},
[`@apply bg-bg-surface-inset`]: {},
input: {
[`@apply bg-[var(${getColorVariableName(
"bg-surface-inset"
)})] cursor-not-allowed`]: {},
[`@apply placeholder-[var(${getColorVariableName("fg-disabled")})]`]:
{},
"@apply bg-bg-surface-inset cursor-not-allowed": {},
"@apply placeholder-fg-disabled": {},
},
"svg > *": {
fill: `var(${getColorVariableName("fg-disabled")}) !important`,
"@apply !fill-fg-disabled": {},
// fill: `var(${getColorVariableName("fg-disabled")}) !important`,
},
},
"svg > *": {
fill: `var(${getColorVariableName("fg-primary")})`,
"@apply fill-fg-primary": {},
// fill: `var(${getColorVariableName("fg-primary")})`,
},
"&:focus, &:focus-visible, &:focus-within, &:active": {
"@apply active-border": {},
Expand All @@ -34,7 +32,7 @@ export const inputComponents: ComponentDef = {

// input field styling
input: {
"@apply appearance-none": {},
"@apply appearance-none grow": {},
"&:focus, &:focus-visible, &:focus-within, &:active": {
"@apply outline-none": {},
},
Expand All @@ -48,9 +46,9 @@ export const inputComponents: ComponentDef = {
// this makes a lot of assumptions about how our svgs are structured
// pretty brittle so fix this later
"> *": {
fill: `var(${getColorVariableName("fg-disabled")}) !important`,
"@apply fill-fg-disabled": {},
},
[`@apply text-[var(${getColorVariableName("fg-disabled")})]`]: {},
"@apply text-fg-disabled": {},
},
},
};
23 changes: 23 additions & 0 deletions packages/alchemy/src/tailwind/components/modal.ts
@@ -0,0 +1,23 @@
import type { ComponentDef } from "../types";

export const modalComponents: ComponentDef = {
".modal": {
"@apply rounded-2xl": {},
"@apply bg-bg-surface-default": {},
"&::backdrop": {
"@apply bg-black bg-opacity-[0.8]": {},
},
".modal-box": {
"@apply z-[1] p-8": {},
},
".modal-backdrop": {
"@apply fixed w-screen h-screen top-0 left-0": {},
"@apply -z-[1] col-start-1 row-start-1 grid self-stretch justify-self-stretch text-transparent":
{},
button: {
opacity: "0",
"@apply h-screen w-screen cursor-default": {},
},
},
},
};

0 comments on commit ebed224

Please sign in to comment.