style: auth screens (#1531)
* chore: invitations empty state * style: new auth screens * chore: update typography * chore: update border colors * chore: resend code text
This commit is contained in:
parent
da6ecd439c
commit
5fadf53580
181 changed files with 682 additions and 645 deletions
|
|
@ -32,6 +32,7 @@ export const EmailCodeForm = ({ handleSignIn }: any) => {
|
|||
setError,
|
||||
setValue,
|
||||
getValues,
|
||||
watch,
|
||||
formState: { errors, isSubmitting, isValid, isDirty },
|
||||
} = useForm<EmailCodeFormValues>({
|
||||
defaultValues: {
|
||||
|
|
@ -112,43 +113,34 @@ export const EmailCodeForm = ({ handleSignIn }: any) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<form className="space-y-5 py-5 px-5">
|
||||
{(codeSent || codeResent) && (
|
||||
<div className="rounded-md bg-green-500/20 p-4">
|
||||
<div className="flex">
|
||||
<div className="flex-shrink-0">
|
||||
<CheckCircleIcon className="h-5 w-5 text-green-500" aria-hidden="true" />
|
||||
</div>
|
||||
<div className="ml-3">
|
||||
<p className="text-sm font-medium text-green-500">
|
||||
{codeResent
|
||||
? "Please check your mail for new code."
|
||||
: "Please check your mail for code."}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
{(codeSent || codeResent) && (
|
||||
<p className="text-center mt-4">
|
||||
We have sent the sign in code.
|
||||
<br />
|
||||
Please check your inbox at <span className="font-medium">{watch("email")}</span>
|
||||
</p>
|
||||
)}
|
||||
<form className="space-y-4 mt-10 w-full sm:w-[360px] mx-auto">
|
||||
<div className="space-y-1">
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
name="email"
|
||||
register={register}
|
||||
validations={{
|
||||
required: "Email ID is required",
|
||||
required: "Email address is required",
|
||||
validate: (value) =>
|
||||
/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
|
||||
value
|
||||
) || "Email ID is not valid",
|
||||
) || "Email address is not valid",
|
||||
}}
|
||||
error={errors.email}
|
||||
placeholder="Enter your Email ID"
|
||||
placeholder="Enter your email address..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
{codeSent && (
|
||||
<div>
|
||||
<>
|
||||
<Input
|
||||
id="token"
|
||||
type="token"
|
||||
|
|
@ -158,14 +150,14 @@ export const EmailCodeForm = ({ handleSignIn }: any) => {
|
|||
required: "Code is required",
|
||||
}}
|
||||
error={errors.token}
|
||||
placeholder="Enter code"
|
||||
placeholder="Enter code..."
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className={`mt-5 flex w-full justify-end text-xs outline-none ${
|
||||
className={`flex w-full justify-end text-xs outline-none ${
|
||||
isResendDisabled
|
||||
? "cursor-default text-custom-text-200"
|
||||
: "cursor-pointer text-custom-primary"
|
||||
: "cursor-pointer text-custom-primary-100"
|
||||
} `}
|
||||
onClick={() => {
|
||||
setIsCodeResending(true);
|
||||
|
|
@ -178,46 +170,43 @@ export const EmailCodeForm = ({ handleSignIn }: any) => {
|
|||
disabled={isResendDisabled}
|
||||
>
|
||||
{resendCodeTimer > 0 ? (
|
||||
<p className="text-right">
|
||||
Didn{"'"}t receive code? Get new code in {resendCodeTimer} seconds.
|
||||
</p>
|
||||
<span className="text-right">Request new code in {resendCodeTimer} seconds</span>
|
||||
) : isCodeResending ? (
|
||||
"Sending code..."
|
||||
"Sending new code..."
|
||||
) : errorResendingCode ? (
|
||||
"Please try again later"
|
||||
) : (
|
||||
"Resend code"
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{codeSent ? (
|
||||
<PrimaryButton
|
||||
type="submit"
|
||||
className="w-full text-center"
|
||||
size="md"
|
||||
onClick={handleSubmit(handleSignin)}
|
||||
disabled={!isValid && isDirty}
|
||||
loading={isLoading}
|
||||
>
|
||||
{isLoading ? "Signing in..." : "Sign in"}
|
||||
</PrimaryButton>
|
||||
) : (
|
||||
<PrimaryButton
|
||||
className="w-full text-center"
|
||||
size="md"
|
||||
onClick={() => {
|
||||
handleSubmit(onSubmit)().then(() => {
|
||||
setResendCodeTimer(30);
|
||||
});
|
||||
}}
|
||||
disabled={!isValid && isDirty}
|
||||
loading={isSubmitting}
|
||||
>
|
||||
{isSubmitting ? "Sending code..." : "Send sign in code"}
|
||||
</PrimaryButton>
|
||||
)}
|
||||
<div>
|
||||
{codeSent ? (
|
||||
<PrimaryButton
|
||||
type="submit"
|
||||
className="w-full text-center"
|
||||
size="md"
|
||||
onClick={handleSubmit(handleSignin)}
|
||||
disabled={!isValid && isDirty}
|
||||
loading={isLoading}
|
||||
>
|
||||
{isLoading ? "Signing in..." : "Sign in"}
|
||||
</PrimaryButton>
|
||||
) : (
|
||||
<PrimaryButton
|
||||
className="w-full text-center"
|
||||
size="md"
|
||||
onClick={() => {
|
||||
handleSubmit(onSubmit)().then(() => {
|
||||
setResendCodeTimer(30);
|
||||
});
|
||||
}}
|
||||
loading={isSubmitting || (!isValid && isDirty)}
|
||||
>
|
||||
{isSubmitting ? "Sending code..." : "Send code"}
|
||||
</PrimaryButton>
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { useForm } from "react-hook-form";
|
|||
// components
|
||||
import { EmailResetPasswordForm } from "components/account";
|
||||
// ui
|
||||
import { Input, SecondaryButton } from "components/ui";
|
||||
import { Input, PrimaryButton } from "components/ui";
|
||||
// types
|
||||
type EmailPasswordFormValues = {
|
||||
email: string;
|
||||
|
|
@ -42,28 +42,38 @@ export const EmailPasswordForm: React.FC<Props> = ({ onSubmit }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<h1 className="text-center text-2xl sm:text-2.5xl font-semibold text-custom-text-100">
|
||||
{isResettingPassword
|
||||
? "Reset your password"
|
||||
: isSignUpPage
|
||||
? "Sign up on Plane"
|
||||
: "Sign in to Plane"}
|
||||
</h1>
|
||||
{isResettingPassword ? (
|
||||
<EmailResetPasswordForm setIsResettingPassword={setIsResettingPassword} />
|
||||
) : (
|
||||
<form className="mt-5 py-5 px-5" onSubmit={handleSubmit(onSubmit)}>
|
||||
<div>
|
||||
<form
|
||||
className="space-y-4 mt-10 w-full sm:w-[360px] mx-auto"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
>
|
||||
<div className="space-y-1">
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
name="email"
|
||||
register={register}
|
||||
validations={{
|
||||
required: "Email ID is required",
|
||||
required: "Email address is required",
|
||||
validate: (value) =>
|
||||
/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
|
||||
value
|
||||
) || "Email ID is not valid",
|
||||
) || "Email address is not valid",
|
||||
}}
|
||||
error={errors.email}
|
||||
placeholder="Enter your email ID"
|
||||
placeholder="Enter your email address..."
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-5">
|
||||
<div className="space-y-1">
|
||||
<Input
|
||||
id="password"
|
||||
type="password"
|
||||
|
|
@ -73,30 +83,28 @@ export const EmailPasswordForm: React.FC<Props> = ({ onSubmit }) => {
|
|||
required: "Password is required",
|
||||
}}
|
||||
error={errors.password}
|
||||
placeholder="Enter your password"
|
||||
placeholder="Enter your password..."
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center justify-between">
|
||||
<div className="ml-auto text-sm">
|
||||
{isSignUpPage ? (
|
||||
<Link href="/">
|
||||
<a className="font-medium text-custom-primary hover:text-custom-primary">
|
||||
Already have an account? Sign in.
|
||||
</a>
|
||||
</Link>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsResettingPassword(true)}
|
||||
className="font-medium text-custom-primary hover:text-custom-primary"
|
||||
>
|
||||
Forgot your password?
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-right text-xs">
|
||||
{isSignUpPage ? (
|
||||
<Link href="/">
|
||||
<a className="text-custom-text-200 hover:text-custom-primary-100">
|
||||
Already have an account? Sign in.
|
||||
</a>
|
||||
</Link>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsResettingPassword(true)}
|
||||
className="text-custom-text-200 hover:text-custom-primary-100"
|
||||
>
|
||||
Forgot your password?
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-5">
|
||||
<SecondaryButton
|
||||
<div>
|
||||
<PrimaryButton
|
||||
type="submit"
|
||||
className="w-full text-center"
|
||||
disabled={!isValid && isDirty}
|
||||
|
|
@ -105,14 +113,14 @@ export const EmailPasswordForm: React.FC<Props> = ({ onSubmit }) => {
|
|||
{isSignUpPage
|
||||
? isSubmitting
|
||||
? "Signing up..."
|
||||
: "Sign Up"
|
||||
: "Sign up"
|
||||
: isSubmitting
|
||||
? "Signing in..."
|
||||
: "Sign In"}
|
||||
</SecondaryButton>
|
||||
: "Sign in"}
|
||||
</PrimaryButton>
|
||||
{!isSignUpPage && (
|
||||
<Link href="/sign-up">
|
||||
<a className="block font-medium text-custom-primary hover:text-custom-primary text-sm mt-1">
|
||||
<a className="block text-custom-text-200 hover:text-custom-primary-100 text-xs mt-4">
|
||||
Don{"'"}t have an account? Sign up.
|
||||
</a>
|
||||
</Link>
|
||||
|
|
|
|||
|
|
@ -59,25 +59,28 @@ export const EmailResetPasswordForm: React.FC<Props> = ({ setIsResettingPassword
|
|||
};
|
||||
|
||||
return (
|
||||
<form className="mt-5 py-5 px-5" onSubmit={handleSubmit(forgotPassword)}>
|
||||
<div>
|
||||
<form
|
||||
className="space-y-4 mt-10 w-full sm:w-[360px] mx-auto"
|
||||
onSubmit={handleSubmit(forgotPassword)}
|
||||
>
|
||||
<div className="space-y-1">
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
name="email"
|
||||
register={register}
|
||||
validations={{
|
||||
required: "Email ID is required",
|
||||
required: "Email address is required",
|
||||
validate: (value) =>
|
||||
/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
|
||||
value
|
||||
) || "Email ID is not valid",
|
||||
) || "Email address is not valid",
|
||||
}}
|
||||
error={errors.email}
|
||||
placeholder="Enter registered Email ID"
|
||||
placeholder="Enter registered email address.."
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-5 flex items-center gap-2">
|
||||
<div className="mt-5 flex flex-col-reverse sm:flex-row items-center gap-2">
|
||||
<SecondaryButton
|
||||
className="w-full text-center"
|
||||
onClick={() => setIsResettingPassword(false)}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
import { useEffect, useState, FC } from "react";
|
||||
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
// next-themes
|
||||
import { useTheme } from "next-themes";
|
||||
// images
|
||||
import githubImage from "/public/logos/github-black.png";
|
||||
import githubBlackImage from "/public/logos/github-black.png";
|
||||
import githubWhiteImage from "/public/logos/github-white.png";
|
||||
|
||||
const { NEXT_PUBLIC_GITHUB_ID } = process.env;
|
||||
|
||||
|
|
@ -11,15 +16,15 @@ export interface GithubLoginButtonProps {
|
|||
handleSignIn: React.Dispatch<string>;
|
||||
}
|
||||
|
||||
export const GithubLoginButton: FC<GithubLoginButtonProps> = (props) => {
|
||||
const { handleSignIn } = props;
|
||||
// router
|
||||
export const GithubLoginButton: FC<GithubLoginButtonProps> = ({ handleSignIn }) => {
|
||||
const [loginCallBackURL, setLoginCallBackURL] = useState(undefined);
|
||||
const [gitCode, setGitCode] = useState<null | string>(null);
|
||||
|
||||
const {
|
||||
query: { code },
|
||||
} = useRouter();
|
||||
// states
|
||||
const [loginCallBackURL, setLoginCallBackURL] = useState(undefined);
|
||||
const [gitCode, setGitCode] = useState<null | string>(null);
|
||||
|
||||
const { theme } = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
if (code && !gitCode) {
|
||||
|
|
@ -35,13 +40,18 @@ export const GithubLoginButton: FC<GithubLoginButtonProps> = (props) => {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<div className="w-full flex justify-center items-center px-[3px]">
|
||||
<div className="w-full flex justify-center items-center">
|
||||
<Link
|
||||
href={`https://github.com/login/oauth/authorize?client_id=${NEXT_PUBLIC_GITHUB_ID}&redirect_uri=${loginCallBackURL}&scope=read:user,user:email`}
|
||||
>
|
||||
<button className="flex w-full items-center justify-center gap-3 rounded border border-custom-border-100 p-2 text-sm font-medium text-custom-text-200 duration-300 hover:bg-custom-background-80">
|
||||
<Image src={githubImage} height={20} width={20} color="#000" alt="GitHub Logo" />
|
||||
<span>Sign In with Github</span>
|
||||
<button className="flex w-full items-center justify-center gap-2 rounded border border-custom-border-300 p-2 text-sm font-medium text-custom-text-100 duration-300 hover:bg-custom-background-80">
|
||||
<Image
|
||||
src={theme === "light" ? githubBlackImage : githubWhiteImage}
|
||||
height={20}
|
||||
width={20}
|
||||
alt="GitHub Logo"
|
||||
/>
|
||||
<span>Sign in with GitHub</span>
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export const GoogleLoginButton: FC<IGoogleLoginButton> = (props) => {
|
|||
theme: "outline",
|
||||
size: "large",
|
||||
logo_alignment: "center",
|
||||
width: "410",
|
||||
width: "360",
|
||||
text: "continue_with",
|
||||
} as GsiButtonConfiguration // customization attributes
|
||||
);
|
||||
|
|
@ -48,7 +48,7 @@ export const GoogleLoginButton: FC<IGoogleLoginButton> = (props) => {
|
|||
<>
|
||||
<Script src="https://accounts.google.com/gsi/client" async defer onLoad={loadScript} />
|
||||
<div
|
||||
className="overflow-hidden rounded w-full flex justify-center items-center"
|
||||
className="overflow-hidden rounded w-full flex justify-center items-center !text-sm !font-medium !text-custom-text-100"
|
||||
id="googleSignInButton"
|
||||
ref={googleSignInButton}
|
||||
/>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue