-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
818 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import * as React from "react"; | ||
import { cva, type VariantProps } from "class-variance-authority"; | ||
import { cn } from "./Card"; | ||
|
||
const avatarVariants = cva( | ||
`relative inline-flex items-center justify-center overflow-hidden bg-app-gray-100 dark:bg-app-gray-600`, | ||
{ | ||
variants: { | ||
size: { | ||
xs: "w-6 h-6", | ||
sm: "w-8 h-8", | ||
md: "w-10 h-10", | ||
lg: "w-14 h-14", | ||
xl: "w-20 h-20", | ||
}, | ||
rounded: { | ||
true: "rounded-full", | ||
false: "rounded-lg", | ||
}, | ||
border: { | ||
true: "p-1 ring-2 ring-app-gray-300 dark:ring-app-gray-500", | ||
false: "", | ||
}, | ||
}, | ||
defaultVariants: { | ||
size: "md", | ||
rounded: true, | ||
border: false, | ||
}, | ||
}, | ||
); | ||
|
||
export interface AvatarProps | ||
extends React.HTMLAttributes<HTMLDivElement>, | ||
VariantProps<typeof avatarVariants> { | ||
children: React.ReactNode; | ||
id?: string; | ||
classes?: Partial<Record<string, string>>; | ||
} | ||
|
||
const Avatar = React.forwardRef<HTMLDivElement, AvatarProps>( | ||
({ className, size, rounded, border, children, id, classes = {}, ...props }, ref) => { | ||
return ( | ||
<div | ||
id={id} | ||
role="button" | ||
className={cn(avatarVariants({ size, rounded, border }), classes.container, className)} | ||
aria-hidden | ||
ref={ref} | ||
{...props} | ||
> | ||
{children} | ||
</div> | ||
); | ||
}, | ||
); | ||
|
||
Avatar.displayName = "Avatar"; | ||
|
||
export { Avatar, avatarVariants }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import * as React from "react"; | ||
import { Button } from "./Button"; | ||
import { Card } from "./Card"; | ||
import { Link } from "./Link"; | ||
|
||
const DocDetails: React.FC = () => { | ||
return ( | ||
<Card className="px-8 py-6 w-full !rounded-2xl !shadow-modal !border-0 dark:!border-app-gray-800 dark:!shadow-dark"> | ||
<div className="mb-4"> | ||
<h3 className="font-semibold text-app-gray-900 dark:text-app-white mb-1"> | ||
Experience Web3Auth, first hand | ||
</h3> | ||
<p className="text-xs text-app-gray-500 dark:text-app-gray-400"> | ||
Browse our full suite of features for your dApp with our docs. Access code examples for | ||
these features by visiting our{" "} | ||
<Link | ||
href="https://web3auth.io/customers.html" | ||
className="text-xs dark:text-app-primary-500" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
playground | ||
</Link> | ||
. | ||
</p> | ||
</div> | ||
<div className="space-y-2"> | ||
<Button | ||
href="https://web3auth.io/docs" | ||
size="sm" | ||
className="gap-2 w-full !border-app-gray-300 !text-app-gray-800 dark:!text-app-white" | ||
variant="secondary" | ||
rel="noopener noreferrer" | ||
> | ||
Read our docs | ||
</Button> | ||
<Button | ||
href="https://web3auth.io/customers" | ||
size="sm" | ||
className="gap-2 w-full !border-app-gray-300 !text-app-gray-800 dark:!text-app-white" | ||
variant="secondary" | ||
rel="noopener noreferrer" | ||
> | ||
Checkout Live Integrations | ||
</Button> | ||
</div> | ||
</Card> | ||
); | ||
}; | ||
|
||
export { DocDetails }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import * as React from "react"; | ||
import { Card } from "./Card"; | ||
import { Icon } from "./Icon"; | ||
import { TextField } from "./TextField"; | ||
import { Button } from "./Button"; | ||
import { LoginForm } from "./LoginForm"; | ||
import { useSocialLogins } from "./useSocialLogin"; | ||
import { SocialLoginObj } from "./types"; | ||
|
||
interface LoginCardProps { | ||
handleEmailPasswordLess: () => void; | ||
handleSocialLogin: (item: SocialLoginObj) => void; | ||
} | ||
|
||
const LoginCard: React.FC<LoginCardProps> = ({handleEmailPasswordLess, handleSocialLogin}) => { | ||
const [loginHint, setLoginHint] = React.useState<string>(""); | ||
|
||
const socialLogins = useSocialLogins(); | ||
|
||
const handlePasswordlessLogin = (e: React.FormEvent) => { | ||
e.preventDefault(); | ||
console.log("loginHint", loginHint); | ||
// Handle passwordless login | ||
handleEmailPasswordLess(); | ||
}; | ||
|
||
const handleSocial = (item: SocialLoginObj, index: number) => { | ||
// Handle social login | ||
handleSocialLogin(item); | ||
}; | ||
|
||
return ( | ||
<div className="mb-6 mt-24 flex justify-center items-center"> | ||
<Card | ||
className="dapp-login-modal !shadow-modal !border-0 dark:!border-app-gray-800 dark:!shadow-dark" | ||
classes={{ container: "!rounded-2xl p-8" }} | ||
> | ||
<div> | ||
<div className="mb-6 flex justify-center items-center"> | ||
<img className="h-11 w-auto" src="https://images.web3auth.io/web3auth-logo-w.svg" alt="" /> | ||
</div> | ||
<p className="text-2xl text-center font-bold text-app-gray-900 dark:text-app-white">Welcome to Web3Auth</p> | ||
<p className="text-base text-center mb-5 text-app-gray-500 dark:text-app-gray-400">Login to continue</p> | ||
</div> | ||
<LoginForm | ||
pill | ||
socialLogins={socialLogins} | ||
showInput={false} | ||
// className="mt-6" | ||
inputExpandBtnProps={{ | ||
pill: true, | ||
size: "xs", | ||
className: "!p-0 !h-[1em] active:!ring-0 focus:!ring-0 !rounded-0", | ||
}} | ||
socialLoginMessage="By continuing, you agree to our terms and conditions." | ||
expandLabel="View more" | ||
collapseLabel="View less" | ||
primaryBtn="input" | ||
onSocialLoginClick={ handleSocial } | ||
> | ||
<form onSubmit={handlePasswordlessLogin}> | ||
<TextField | ||
value={loginHint} | ||
onChange={(e) => setLoginHint(e.target.value)} | ||
label="Email or Phone" | ||
pill={true} | ||
type="email" | ||
className="w-full" | ||
required | ||
placeholder="E.g. +00-123455/[email protected]" | ||
/> | ||
<Button type="submit" className="my-4" variant="primary" block> | ||
Continue with Email or Phone | ||
</Button> | ||
</form> | ||
</LoginForm> | ||
<div className="flex items-center justify-center mt-8"> | ||
<img src="/assets/ws-trademark-light.svg" alt="web3auth logo" className="block dark:hidden h-5" /> | ||
<img src="/assets/ws-trademark-dark.svg" alt="web3auth logo" className="hidden dark:block h-5" /> | ||
</div> | ||
</Card> | ||
</div> | ||
); | ||
}; | ||
|
||
export { LoginCard }; |
156 changes: 156 additions & 0 deletions
156
demo/redirect-flow-example/src/components/LoginForm.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
import * as React from "react"; | ||
import { useState } from "react"; | ||
import { Button } from "./Button"; | ||
import { Icon } from "./Icon"; | ||
import { TextField } from "./TextField"; | ||
import { cn } from "./Card"; | ||
import { Image } from "./Image"; | ||
import { LoginFormProps } from "./types"; | ||
|
||
const LoginForm: React.FC<LoginFormProps> = ({ | ||
socialLogins = [], | ||
pill = false, | ||
expandLabel = "View More", | ||
collapseLabel = "View Less", | ||
socialLoginMessage = "We do not store any data related to your social logins.", | ||
showInput = true, | ||
inputBtnLabel = "", | ||
inputProps = {}, | ||
inputExpandBtnProps = {}, | ||
gridCols = 3, | ||
inputBtnProps = {}, | ||
primaryBtn = "social", | ||
classes = {}, | ||
isExistingLogin = false, | ||
existingLoginProps = {}, | ||
existingLabelInline = false, | ||
divider = false, | ||
onSocialLoginClick, | ||
onExistingLoginClick, | ||
onInputBtnClick, | ||
children, | ||
}) => { | ||
const [viewMoreOptions, setViewMoreOptions] = useState(false); | ||
const [imagesLoaded, setImagesLoaded] = useState(false); | ||
|
||
const getIcon = (provider: string) => { | ||
if (provider === "twitter") { | ||
return "twitter-x"; | ||
} | ||
return provider; | ||
}; | ||
|
||
const toggleViewMoreOptions = () => { | ||
setViewMoreOptions(!viewMoreOptions); | ||
if (!imagesLoaded) { | ||
setImagesLoaded(true); | ||
} | ||
}; | ||
|
||
const isHiddenIcon = (index: number) => { | ||
if (imagesLoaded) return false; | ||
return !viewMoreOptions && index > 3; | ||
}; | ||
|
||
return ( | ||
<div className={cn("w-full flex flex-col", classes.container)}> | ||
{isExistingLogin && existingLoginProps?.verifier && ( | ||
<Button | ||
size={existingLabelInline ? "xl" : "md"} | ||
className={cn("mb-4", classes.existingBtn)} | ||
onClick={() => onExistingLoginClick && onExistingLoginClick(existingLoginProps)} | ||
> | ||
<div className="flex items-center justify-center gap-3"> | ||
<Icon | ||
name={existingLoginProps?.icon || ""} | ||
className={cn("w-6", existingLoginProps?.iconStyle)} | ||
size={existingLoginProps?.iconSize || "24"} | ||
/> | ||
<p className={cn("text-sm font-medium flex items-center gap-1", { "flex-col": existingLabelInline })}> | ||
<span className="capitalize">{existingLoginProps?.label || "Continue With"} {existingLoginProps?.verifier || ""}</span> | ||
<span className="font-semibold">{existingLoginProps.loginHint}</span> | ||
</p> | ||
</div> | ||
</Button> | ||
)} | ||
{socialLogins.length > 0 && ( | ||
<div className={cn( | ||
"overflow-y-hidden grid gap-4 -m-1 p-1 transition-all duration-300 ease-in-out", | ||
{ "max-h-[500px]": viewMoreOptions, "max-h-[106px]": !viewMoreOptions, "grid-cols-3": gridCols === 3, "grid-cols-4": gridCols === 2 }, | ||
classes.loginItemContainer | ||
)}> | ||
{socialLogins.map((item, index) => ( | ||
<div | ||
key={item.icon} | ||
className={cn("group", { | ||
"col-span-3": !isExistingLogin && (item?.block || index === 0), | ||
"col-span-2": gridCols === 2, | ||
"col-span-4": gridCols === 2 && (item?.block || index === 0), | ||
})} | ||
> | ||
<Button | ||
type="button" | ||
block | ||
className={"rounded-full"} | ||
aria-label={`${item.icon} Login Button`} | ||
variant="secondary" | ||
onClick={() => onSocialLoginClick && onSocialLoginClick(item, index)} | ||
> | ||
<div> | ||
<Image isHidden={isHiddenIcon(index)} icon={getIcon(item.icon || "")} /> | ||
</div> | ||
{item?.description && !isExistingLogin && ( | ||
<div className="flex flex-col items-center ml-2"> | ||
{item?.description} | ||
</div> | ||
)} | ||
</Button> | ||
</div> | ||
))} | ||
</div> | ||
)} | ||
{socialLoginMessage && ( | ||
<p className={cn("text-xs font-medium text-app-gray-500 dark:text-app-gray-200 mt-4", classes.socialLoginMsg)}> | ||
{socialLoginMessage} | ||
</p> | ||
)} | ||
{socialLogins.length > 0 && socialLogins.length > 4 && ( | ||
<div className={cn("flex items-center justify-end my-4", { "my-2": divider }, classes.expandBtnContainer)}> | ||
<Button | ||
variant="text" | ||
pill={pill} | ||
{...inputExpandBtnProps} | ||
className={cn("text-sm font-medium", classes.expandBtn)} | ||
onClick={toggleViewMoreOptions} | ||
> | ||
{viewMoreOptions ? collapseLabel : expandLabel} | ||
</Button> | ||
</div> | ||
)} | ||
{divider && ( | ||
<div className="flex items-center mb-2 gap-2"> | ||
<div className="h-[1px] w-full bg-app-gray-200 dark:bg-app-gray-600"></div> | ||
<span className="text-app-gray-600 dark:text-app-gray-200 text-sm font-normal">or</span> | ||
<div className="h-[1px] w-full bg-app-gray-200 dark:bg-app-gray-600"></div> | ||
</div> | ||
)} | ||
{children} | ||
{showInput && ( | ||
<> | ||
<TextField {...inputProps} pill={pill} /> | ||
<Button | ||
className="my-4" | ||
{...inputBtnProps} | ||
variant={!isExistingLogin && primaryBtn === "input" ? "primary" : "tertiary"} | ||
block | ||
onClick={onInputBtnClick} | ||
> | ||
{inputBtnLabel} | ||
</Button> | ||
</> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export { LoginForm }; |
Oops, something went wrong.