Merge pull request #3905 from Infisical/password-reset-ui

improvement(password-reset): re-vamp password reset flow pages/steps to match login
This commit is contained in:
Scott Wilson
2025-07-03 10:31:58 -07:00
committed by GitHub
6 changed files with 155 additions and 120 deletions
@@ -1,19 +1,33 @@
import { Helmet } from "react-helmet"; import { Helmet } from "react-helmet";
import { Link } from "@tanstack/react-router";
export const EmailNotVerifiedPage = () => { export const EmailNotVerifiedPage = () => {
return ( return (
<div className="flex flex-col justify-between bg-bunker-800 md:h-screen"> <div className="flex min-h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<Helmet> <Helmet>
<title>Request a New Invite</title> <title>Request a New Invite</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
</Helmet> </Helmet>
<div className="flex h-screen w-screen flex-col items-center justify-center text-gray-200"> <Link to="/">
<p className="text-6xl">Oops.</p> <div className="mb-4 mt-20 flex justify-center">
<p className="mb-1 mt-2 text-xl">Your email was not verified. </p> <img src="/images/gradientLogo.svg" className="h-[90px] w-[120px]" alt="Infisical Logo" />
<p className="text-xl">Please try again.</p> </div>
<p className="text-md mt-8 max-w-sm text-center text-gray-600"> </Link>
Note: If it still doesn&apos;t work, please reach out to us at support@infisical.com <div className="mx-auto flex w-full flex-col items-center justify-center">
<h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Your email was not verified
</h1>
<p className="w-max justify-center text-center text-sm text-gray-400">
Please try again. <br /> Note: If it still doesn&apos;t work, please reach out to us at
support@infisical.com
</p> </p>
<div className="mt-6 flex flex-row text-sm text-bunker-400">
<Link to="/login">
<span className="cursor-pointer duration-200 hover:text-bunker-200 hover:underline hover:decoration-primary-700 hover:underline-offset-4">
Back to Login
</span>
</Link>
</div>
</div> </div>
</div> </div>
); );
@@ -1,7 +1,7 @@
import { useState } from "react"; import { useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { useNavigate } from "@tanstack/react-router"; import { Link, useNavigate } from "@tanstack/react-router";
import { z } from "zod"; import { z } from "zod";
import { UserEncryptionVersion } from "@app/hooks/api/auth/types"; import { UserEncryptionVersion } from "@app/hooks/api/auth/types";
@@ -36,7 +36,12 @@ export const PasswordResetPage = () => {
const navigate = useNavigate(); const navigate = useNavigate();
return ( return (
<div className="flex h-screen w-full flex-col items-center justify-center bg-bunker-800"> <div className="flex min-h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<Link to="/">
<div className="mb-4 mt-20 flex justify-center">
<img src="/images/gradientLogo.svg" className="h-[90px] w-[120px]" alt="Infisical Logo" />
</div>
</Link>
{step === Steps.ConfirmEmail && ( {step === Steps.ConfirmEmail && (
<ConfirmEmailStep <ConfirmEmailStep
onComplete={(verifyToken, userEncryptionVersion) => { onComplete={(verifyToken, userEncryptionVersion) => {
@@ -19,17 +19,21 @@ export const ConfirmEmailStep = ({ onComplete }: Props) => {
isPending: isVerifyPasswordResetLoading isPending: isVerifyPasswordResetLoading
} = useVerifyPasswordResetCode(); } = useVerifyPasswordResetCode();
return ( return (
<div className="mx-1 my-32 flex w-full max-w-xs flex-col items-center rounded-xl bg-bunker px-4 py-6 drop-shadow-xl md:max-w-lg md:px-6"> <div className="mx-auto flex w-full flex-col items-center justify-center">
<p className="mb-8 flex justify-center bg-gradient-to-br from-sky-400 to-primary bg-clip-text text-center text-4xl font-semibold text-transparent"> <h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Confirm your email Confirm your email
</h1>
<p className="mb-8 w-max justify-center text-center text-sm text-gray-400">
Reset password for <span className="italic">{email}</span>.
</p> </p>
<img <div className="w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
src="/images/envelope.svg"
style={{ height: "262px", width: "410px" }}
alt="verify email"
/>
<div className="mx-auto mb-2 mt-4 flex max-h-24 max-w-md flex-col items-center justify-center px-4 text-lg md:p-2">
<Button <Button
type="submit"
size="sm"
isFullWidth
className="h-10"
colorSchema="primary"
variant="solid"
onClick={async () => { onClick={async () => {
try { try {
const response = await verifyPasswordResetCodeMutateAsync({ const response = await verifyPasswordResetCodeMutateAsync({
@@ -44,7 +48,6 @@ export const ConfirmEmailStep = ({ onComplete }: Props) => {
} }
}} }}
isLoading={isVerifyPasswordResetLoading} isLoading={isVerifyPasswordResetLoading}
size="lg"
> >
Confirm Email Confirm Email
</Button> </Button>
@@ -1,7 +1,7 @@
import crypto from "crypto"; import crypto from "crypto";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { faCheck, faX } from "@fortawesome/free-solid-svg-icons"; import { faCheck, faXmark } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { useSearch } from "@tanstack/react-router"; import { useSearch } from "@tanstack/react-router";
@@ -169,17 +169,15 @@ export const EnterPasswordStep = ({
return ( return (
<form <form
onSubmit={handleSubmit(resetPasswordHandler)} onSubmit={handleSubmit(resetPasswordHandler)}
className="mx-1 my-32 flex w-full max-w-xs flex-col items-center rounded-xl bg-bunker px-4 pb-3 pt-6 drop-shadow-xl md:max-w-lg md:px-6" className="mx-auto flex w-full flex-col items-center justify-center"
> >
<p className="mx-auto flex w-max justify-center text-2xl font-semibold text-bunker-100 md:text-3xl"> <h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Enter new password Enter new password
</h1>
<p className="w-max justify-center text-center text-sm text-gray-400">
Make sure you save it somewhere safe.
</p> </p>
<div className="mt-1 flex flex-row items-center justify-center md:mx-2 md:pb-4"> <div className="mt-8 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
<p className="flex w-max max-w-md justify-center text-sm text-gray-400">
Make sure you save it somewhere safe.
</p>
</div>
<div className="mt-4 flex max-h-24 w-full items-center justify-center rounded-lg md:mt-0 md:max-h-28 md:p-2">
<Controller <Controller
control={control} control={control}
name="password" name="password"
@@ -202,6 +200,20 @@ export const EnterPasswordStep = ({
)} )}
/> />
</div> </div>
<div className="w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
<Button
type="submit"
size="sm"
isFullWidth
className="h-10"
colorSchema="primary"
variant="solid"
isLoading={isSubmitting || isLoading || isLoadingV2}
isDisabled={isSubmitting || isLoading || isLoadingV2}
>
Change Password
</Button>
</div>
{passwordErrorTooShort || {passwordErrorTooShort ||
passwordErrorTooLong || passwordErrorTooLong ||
passwordErrorNoLetterChar || passwordErrorNoLetterChar ||
@@ -210,33 +222,33 @@ export const EnterPasswordStep = ({
passwordErrorEscapeChar || passwordErrorEscapeChar ||
passwordErrorLowEntropy || passwordErrorLowEntropy ||
passwordErrorBreached ? ( passwordErrorBreached ? (
<div className="mx-2 mb-2 mt-3 flex w-full max-w-md flex-col items-start rounded-md bg-white/5 px-2 py-2"> <div className="mt-4 rounded border border-mineshaft-600 bg-mineshaft-800 p-4 drop-shadow">
<div className="mb-1 text-sm text-gray-400">Password should contain:</div> <div className="mb-1 ml-2 text-sm text-gray-300">Password should contain:</div>
<div className="ml-1 flex flex-row items-center justify-start"> <div className="ml-2 flex flex-row items-center justify-start">
{passwordErrorTooShort ? ( {passwordErrorTooShort ? (
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" /> <FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" /> <FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
)} )}
<div className={`${passwordErrorTooShort ? "text-gray-400" : "text-gray-600"} text-sm`}> <div className={`${passwordErrorTooShort ? "text-gray-400" : "text-gray-600"} text-sm`}>
at least 14 characters at least 14 characters
</div> </div>
</div> </div>
<div className="ml-1 flex flex-row items-center justify-start"> <div className="ml-2 flex flex-row items-center justify-start">
{passwordErrorTooLong ? ( {passwordErrorTooLong ? (
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" /> <FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" /> <FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
)} )}
<div className={`${passwordErrorTooLong ? "text-gray-400" : "text-gray-600"} text-sm`}> <div className={`${passwordErrorTooLong ? "text-gray-400" : "text-gray-600"} text-sm`}>
at most 100 characters at most 100 characters
</div> </div>
</div> </div>
<div className="ml-1 flex flex-row items-center justify-start"> <div className="ml-2 flex flex-row items-center justify-start">
{passwordErrorNoLetterChar ? ( {passwordErrorNoLetterChar ? (
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" /> <FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" /> <FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
)} )}
<div <div
className={`${passwordErrorNoLetterChar ? "text-gray-400" : "text-gray-600"} text-sm`} className={`${passwordErrorNoLetterChar ? "text-gray-400" : "text-gray-600"} text-sm`}
@@ -244,11 +256,11 @@ export const EnterPasswordStep = ({
at least 1 letter character at least 1 letter character
</div> </div>
</div> </div>
<div className="ml-1 flex flex-row items-center justify-start"> <div className="ml-2 flex flex-row items-center justify-start">
{passwordErrorNoNumOrSpecialChar ? ( {passwordErrorNoNumOrSpecialChar ? (
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" /> <FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" /> <FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
)} )}
<div <div
className={`${ className={`${
@@ -258,11 +270,11 @@ export const EnterPasswordStep = ({
at least 1 number or special character at least 1 number or special character
</div> </div>
</div> </div>
<div className="ml-1 flex flex-row items-center justify-start"> <div className="ml-2 flex flex-row items-center justify-start">
{passwordErrorRepeatedChar ? ( {passwordErrorRepeatedChar ? (
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" /> <FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" /> <FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
)} )}
<div <div
className={`${passwordErrorRepeatedChar ? "text-gray-400" : "text-gray-600"} text-sm`} className={`${passwordErrorRepeatedChar ? "text-gray-400" : "text-gray-600"} text-sm`}
@@ -270,11 +282,11 @@ export const EnterPasswordStep = ({
at most 3 repeated, consecutive characters at most 3 repeated, consecutive characters
</div> </div>
</div> </div>
<div className="ml-1 flex flex-row items-center justify-start"> <div className="ml-2 flex flex-row items-center justify-start">
{passwordErrorEscapeChar ? ( {passwordErrorEscapeChar ? (
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" /> <FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" /> <FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
)} )}
<div <div
className={`${passwordErrorEscapeChar ? "text-gray-400" : "text-gray-600"} text-sm`} className={`${passwordErrorEscapeChar ? "text-gray-400" : "text-gray-600"} text-sm`}
@@ -282,11 +294,11 @@ export const EnterPasswordStep = ({
No escape characters allowed. No escape characters allowed.
</div> </div>
</div> </div>
<div className="ml-1 flex flex-row items-center justify-start"> <div className="ml-2 flex flex-row items-center justify-start">
{passwordErrorLowEntropy ? ( {passwordErrorLowEntropy ? (
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" /> <FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" /> <FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
)} )}
<div <div
className={`${passwordErrorLowEntropy ? "text-gray-400" : "text-gray-600"} text-sm`} className={`${passwordErrorLowEntropy ? "text-gray-400" : "text-gray-600"} text-sm`}
@@ -294,32 +306,18 @@ export const EnterPasswordStep = ({
Password contains personal info. Password contains personal info.
</div> </div>
</div> </div>
<div className="ml-1 flex flex-row items-center justify-start"> <div className="ml-2 flex flex-row items-center justify-start">
{passwordErrorBreached ? ( {passwordErrorBreached ? (
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" /> <FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" /> <FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
)} )}
<div className={`${passwordErrorBreached ? "text-gray-400" : "text-gray-600"} text-sm`}> <div className={`${passwordErrorBreached ? "text-gray-400" : "text-gray-600"} text-sm`}>
Password was found in a data breach. Password was found in a data breach.
</div> </div>
</div> </div>
</div> </div>
) : ( ) : null}
<div className="py-2" />
)}
<div className="mx-auto mt-4 flex max-h-20 w-full max-w-md flex-col items-center justify-center text-sm md:p-2">
<div className="text-l m-8 mt-6 px-8 py-3 text-lg">
<Button
type="submit"
colorSchema="secondary"
isLoading={isSubmitting || isLoading || isLoadingV2}
isDisabled={isSubmitting || isLoading || isLoadingV2}
>
Change Password
</Button>
</div>
</div>
</form> </form>
); );
}; };
@@ -43,18 +43,15 @@ export const InputBackupKeyStep = ({ verificationToken, onComplete }: Props) =>
return ( return (
<form <form
onSubmit={handleSubmit(getEncryptedKeyHandler)} onSubmit={handleSubmit(getEncryptedKeyHandler)}
className="mx-1 my-32 flex w-full max-w-xs flex-col items-center rounded-xl bg-bunker px-4 pb-3 pt-6 drop-shadow-xl md:max-w-lg md:px-6" className="mx-auto flex w-full flex-col items-center justify-center"
> >
<p className="mx-auto mb-4 flex w-max justify-center text-2xl font-semibold text-bunker-100"> <h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Enter your backup key Enter your backup key
</h1>
<p className="w-max justify-center text-center text-sm text-gray-400">
You can find it in your emergency kit you downloaded during signup.
</p> </p>
<div className="mt-4 flex flex-row items-center justify-center md:mx-2 md:pb-4"> <div className="mt-8 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
<p className="flex w-full px-4 text-center text-sm text-gray-400 sm:max-w-md">
You can find it in your emergency kit. You had to download the emergency kit during
signup.
</p>
</div>
<div className="mt-4 flex max-h-24 w-full items-center justify-center rounded-lg md:mt-0 md:max-h-28 md:p-2">
<Controller <Controller
control={control} control={control}
name="backupKey" name="backupKey"
@@ -75,12 +72,17 @@ export const InputBackupKeyStep = ({ verificationToken, onComplete }: Props) =>
)} )}
/> />
</div> </div>
<div className="mx-auto mt-4 flex max-h-20 w-full max-w-md flex-col items-center justify-center text-sm md:p-2"> <div className="w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
<div className="text-l m-8 mt-6 px-8 py-3 text-lg"> <Button
<Button type="submit" colorSchema="secondary"> type="submit"
Submit Backup Key size="sm"
</Button> isFullWidth
</div> className="h-10"
colorSchema="primary"
variant="solid"
>
Submit Backup Key
</Button>
</div> </div>
</form> </form>
); );
@@ -2,8 +2,7 @@ import { FormEvent, useState } from "react";
import { Helmet } from "react-helmet"; import { Helmet } from "react-helmet";
import { Link } from "@tanstack/react-router"; import { Link } from "@tanstack/react-router";
import InputField from "@app/components/basic/InputField"; import { Button, EmailServiceSetupModal, Input } from "@app/components/v2";
import { Button, EmailServiceSetupModal } from "@app/components/v2";
import { usePopUp } from "@app/hooks"; import { usePopUp } from "@app/hooks";
import { useSendPasswordResetEmail } from "@app/hooks/api"; import { useSendPasswordResetEmail } from "@app/hooks/api";
import { useFetchServerStatus } from "@app/hooks/api/serverDetails"; import { useFetchServerStatus } from "@app/hooks/api/serverDetails";
@@ -44,9 +43,9 @@ export const VerifyEmailPage = () => {
}; };
return ( return (
<div className="flex h-screen flex-col justify-start bg-bunker-800 px-6"> <div className="flex min-h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<Helmet> <Helmet>
<title>Login</title> <title>Reset Password</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
<meta property="og:image" content="/images/message.png" /> <meta property="og:image" content="/images/message.png" />
<meta property="og:title" content="Verify your email in Infisical" /> <meta property="og:title" content="Verify your email in Infisical" />
@@ -56,66 +55,80 @@ export const VerifyEmailPage = () => {
/> />
</Helmet> </Helmet>
<Link to="/"> <Link to="/">
<div className="mb-8 mt-20 flex cursor-pointer justify-center"> <div className="mb-4 mt-20 flex justify-center">
<img <img
src="/images/biglogo.png" src="/images/gradientLogo.svg"
style={{ style={{
height: "90px", height: "90px",
width: "120px" width: "120px"
}} }}
alt="long logo" alt="Infisical Logo"
/> />
</div> </div>
</Link> </Link>
{step === 1 && ( {step === 1 && (
<form <form
onSubmit={onSubmit} onSubmit={onSubmit}
className="h-7/12 mx-auto w-full max-w-md rounded-xl bg-bunker px-6 py-4 pt-8 drop-shadow-xl" className="mx-auto flex w-full flex-col items-center justify-center"
> >
<p className="mx-auto mb-6 flex w-max justify-center text-2xl font-semibold text-bunker-100 md:text-3xl"> <h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Forgot your password? Forgot your password?
</h1>
<p className="w-max justify-center text-center text-sm text-gray-400">
Enter your email to start the password reset process. <br /> You will receive an email
with instructions.
</p> </p>
<div className="mt-4 flex flex-row items-center justify-center md:mx-2 md:pb-4"> <div className="mt-8 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
<p className="flex w-max justify-center text-center text-sm text-gray-400"> <Input
Enter your email to start the password reset process. You will receive an email with
instructions.
</p>
</div>
<div className="mt-4 flex max-h-24 w-full items-center justify-center rounded-lg md:mt-0 md:max-h-28 md:p-2">
<InputField
label="Email"
onChangeHandler={setEmail}
type="email"
value={email} value={email}
placeholder="" onChange={(e) => setEmail(e.target.value)}
type="email"
placeholder="Enter your email..."
isRequired isRequired
autoComplete="username" autoComplete="username"
className="h-10"
/> />
</div> </div>
<div className="mx-auto mt-4 flex max-h-20 w-full max-w-md flex-col items-center justify-center text-sm md:p-2"> <div className="mt-4 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
<div className="text-l m-8 mt-6 px-8 py-3 text-lg"> <Button
<Button type="submit" size="lg" onClick={() => {}} isLoading={loading}> type="submit"
Continue size="sm"
</Button> isFullWidth
</div> className="h-10"
colorSchema="primary"
variant="solid"
isLoading={loading}
>
Continue
</Button>
</div>
<div className="mt-6 flex flex-row text-sm text-bunker-400">
<Link to="/login">
<span className="cursor-pointer duration-200 hover:text-bunker-200 hover:underline hover:decoration-primary-700 hover:underline-offset-4">
Back to Login
</span>
</Link>
</div> </div>
</form> </form>
)} )}
{step === 2 && ( {step === 2 && (
<div className="h-7/12 mx-auto w-full max-w-md rounded-xl bg-bunker px-6 py-4 pt-8 drop-shadow-xl"> <div className="mx-auto flex w-full flex-col items-center justify-center">
<p className="mx-auto mb-6 flex w-max justify-center text-xl font-semibold text-bunker-100 md:text-2xl"> <h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Look for an email in your inbox. Look for an email in your inbox
</h1>
<p className="w-max max-w-lg justify-center text-center text-sm text-gray-400">
If the email is in our system, you will receive an email at{" "}
<span className="italic">{email}</span> with instructions on how to reset your password.
</p> </p>
<div className="mt-4 flex flex-row items-center justify-center md:mx-2 md:pb-4"> <div className="mt-6 flex flex-row text-sm text-bunker-400">
<p className="w-max text-center text-sm text-gray-400"> <Link to="/login">
If the email is in our system, you will receive an email at{" "} <span className="cursor-pointer duration-200 hover:text-bunker-200 hover:underline hover:decoration-primary-700 hover:underline-offset-4">
<span className="italic">{email}</span> with instructions on how to reset your Back to Login
password. </span>
</p> </Link>
</div> </div>
</div> </div>
)} )}
<EmailServiceSetupModal <EmailServiceSetupModal
isOpen={popUp.setUpEmail?.isOpen} isOpen={popUp.setUpEmail?.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle("setUpEmail", isOpen)} onOpenChange={(isOpen) => handlePopUpToggle("setUpEmail", isOpen)}