Dark mode login screens (#2483)

* multi-user auth screen ui update

* dark mode login screen + recovery key modals

* remove unneeded import
This commit is contained in:
Sean Hatfield 2024-10-15 14:41:23 -07:00 committed by GitHub
parent 79898610cc
commit 66a81c21b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 93 additions and 81 deletions

View File

@ -2,6 +2,7 @@ import showToast from "@/utils/toast";
import { DownloadSimple, Key } from "@phosphor-icons/react"; import { DownloadSimple, Key } from "@phosphor-icons/react";
import { saveAs } from "file-saver"; import { saveAs } from "file-saver";
import { useState } from "react"; import { useState } from "react";
import ModalWrapper from "@/components/ModalWrapper";
export default function RecoveryCodeModal({ export default function RecoveryCodeModal({
recoveryCodes, recoveryCodes,
@ -32,55 +33,59 @@ export default function RecoveryCodeModal({
}; };
return ( return (
<div className="inline-block bg-secondary rounded-lg text-left overflow-hidden shadow-xl transform transition-all border-2 border-[#BCC9DB]/10 w-[600px] mx-4"> <ModalWrapper isOpen={true}>
<div className="md:py-[35px] md:px-[50px] py-[28px] px-[20px]"> <div className="w-full max-w-2xl bg-theme-bg-secondary rounded-lg shadow border-2 border-theme-modal-border overflow-hidden">
<div className="flex gap-x-2"> <div className="relative p-6 border-b rounded-t border-theme-modal-border">
<Key size={24} className="text-white" weight="bold" /> <div className="w-full flex gap-x-2 items-center">
<h3 <Key size={24} className="text-white" weight="bold" />
className="text-lg leading-6 font-medium text-white" <h3 className="text-xl font-semibold text-white overflow-hidden overflow-ellipsis whitespace-nowrap">
id="modal-headline" Recovery Codes
> </h3>
Recovery Codes </div>
</h3>
</div> </div>
<div className="mt-4"> <div
<p className="text-sm text-white flex flex-col"> className="h-full w-full overflow-y-auto"
In order to reset your password in the future, you will need these style={{ maxHeight: "calc(100vh - 200px)" }}
recovery codes. Download or copy your recovery codes to save them.{" "} >
<br /> <div className="py-7 px-9 space-y-2 flex-col">
<b className="mt-4">These recovery codes are only shown once!</b> <p className="text-sm text-white flex flex-col">
</p> In order to reset your password in the future, you will need these
<div recovery codes. Download or copy your recovery codes to save them.{" "}
className="bg-dark-highlight text-white hover:text-primary-button <br />
flex items-center justify-center rounded-md mt-6 cursor-pointer" <b className="mt-4">These recovery codes are only shown once!</b>
onClick={handleCopyToClipboard} </p>
> <div
<ul className="space-y-2 md:p-6 p-4"> className="bg-theme-settings-input-bg text-white hover:text-primary-button
{recoveryCodes.map((code, index) => ( flex items-center justify-center rounded-md mt-6 cursor-pointer"
<li key={index} className="md:text-sm text-xs"> onClick={handleCopyToClipboard}
{code} >
</li> <ul className="space-y-2 md:p-6 p-4">
))} {recoveryCodes.map((code, index) => (
</ul> <li key={index} className="md:text-sm text-xs">
{code}
</li>
))}
</ul>
</div>
</div>
<div className="flex w-full justify-end items-center p-6 space-x-2 border-t border-theme-modal-border rounded-b">
<button
type="button"
className="transition-all duration-300 bg-white text-black hover:opacity-60 px-4 py-2 rounded-lg text-sm flex items-center gap-x-2"
onClick={downloadClicked ? handleClose : downloadRecoveryCodes}
>
{downloadClicked ? (
"Close"
) : (
<>
<DownloadSimple weight="bold" size={18} />
<p>Download</p>
</>
)}
</button>
</div> </div>
</div> </div>
</div> </div>
<div className="flex w-full justify-center items-center p-3 space-x-2 rounded-b border-gray-500/50 -mt-4 mb-4"> </ModalWrapper>
<button
type="button"
className="transition-all duration-300 text-xs md:w-[500px] md:h-[34px] h-[48px] w-full m-2 font-semibold rounded-lg bg-primary-button hover:bg-secondary border-2 border-transparent hover:border-primary-button hover:text-white whitespace-nowrap shadow-[0_4px_14px_rgba(0,0,0,0.25)] flex justify-center items-center gap-x-2"
onClick={downloadClicked ? handleClose : downloadRecoveryCodes}
>
{downloadClicked ? (
"Close"
) : (
<>
<DownloadSimple weight="bold" size={18} />
<p>Download</p>
</>
)}
</button>
</div>
</div>
); );
} }

View File

@ -32,7 +32,7 @@ const RecoveryForm = ({ onSubmit, setShowRecoveryForm }) => {
return ( return (
<form <form
onSubmit={handleSubmit} onSubmit={handleSubmit}
className="flex flex-col justify-center items-center relative rounded-2xl md:bg-login-gradient md:shadow-[0_4px_14px_rgba(0,0,0,0.25)] md:px-8 px-0 py-4 w-full md:w-fit mt-10 md:mt-0" className="flex flex-col justify-center items-center relative rounded-2xl bg-theme-bg-secondary md:shadow-[0_4px_14px_rgba(0,0,0,0.25)] md:px-8 px-0 py-4 w-full md:w-fit mt-10 md:mt-0"
> >
<div className="flex items-start justify-between pt-11 pb-9 w-screen md:w-full md:px-12 px-6 "> <div className="flex items-start justify-between pt-11 pb-9 w-screen md:w-full md:px-12 px-6 ">
<div className="flex flex-col gap-y-4 w-full"> <div className="flex flex-col gap-y-4 w-full">
@ -56,7 +56,7 @@ const RecoveryForm = ({ onSubmit, setShowRecoveryForm }) => {
placeholder={t("login.multi-user.placeholder-username")} placeholder={t("login.multi-user.placeholder-username")}
value={username} value={username}
onChange={(e) => setUsername(e.target.value)} onChange={(e) => setUsername(e.target.value)}
className="bg-zinc-900 text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-md p-2.5 w-full h-[48px] md:w-[300px] md:h-[34px]" className="bg-theme-settings-input-bg text-theme-text-primary placeholder:text-theme-settings-input-placeholder focus:outline-primary-button active:outline-primary-button outline-none text-sm rounded-md p-2.5 w-full h-[48px] md:w-[300px] md:h-[34px]"
required required
/> />
</div> </div>
@ -76,7 +76,7 @@ const RecoveryForm = ({ onSubmit, setShowRecoveryForm }) => {
onChange={(e) => onChange={(e) =>
handleRecoveryCodeChange(index, e.target.value) handleRecoveryCodeChange(index, e.target.value)
} }
className="bg-zinc-900 text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-md p-2.5 w-full h-[48px] md:w-[300px] md:h-[34px]" className="bg-theme-settings-input-bg text-theme-text-primary placeholder:text-theme-settings-input-placeholder focus:outline-primary-button active:outline-primary-button outline-none text-sm rounded-md p-2.5 w-full h-[48px] md:w-[300px] md:h-[34px]"
required required
/> />
</div> </div>
@ -115,7 +115,7 @@ const ResetPasswordForm = ({ onSubmit }) => {
return ( return (
<form <form
onSubmit={handleSubmit} onSubmit={handleSubmit}
className="flex flex-col justify-center items-center relative rounded-2xl md:bg-login-gradient md:shadow-[0_4px_14px_rgba(0,0,0,0.25)] md:px-12 px-0 py-4 w-full md:w-fit -mt-24 md:-mt-28" className="flex flex-col justify-center items-center relative rounded-2xl bg-theme-bg-secondary md:shadow-[0_4px_14px_rgba(0,0,0,0.25)] md:px-12 px-0 py-4 w-full md:w-fit -mt-24 md:-mt-28"
> >
<div className="flex items-start justify-between pt-11 pb-9 w-screen md:w-full md:px-12 px-6"> <div className="flex items-start justify-between pt-11 pb-9 w-screen md:w-full md:px-12 px-6">
<div className="flex flex-col gap-y-4 w-full"> <div className="flex flex-col gap-y-4 w-full">
@ -281,7 +281,7 @@ export default function MultiUserAuth() {
return ( return (
<> <>
<form onSubmit={handleLogin}> <form onSubmit={handleLogin}>
<div className="flex flex-col justify-center items-center relative rounded-2xl md:bg-login-gradient md:shadow-[0_4px_14px_rgba(0,0,0,0.25)] md:px-12 py-12 -mt-4 md:mt-0"> <div className="flex flex-col justify-center items-center relative rounded-2xl bg-theme-bg-secondary md:shadow-[0_4px_14px_rgba(0,0,0,0.25)] md:px-12 py-12 -mt-4 md:mt-0">
<div className="flex items-start justify-between pt-11 pb-9 rounded-t"> <div className="flex items-start justify-between pt-11 pb-9 rounded-t">
<div className="flex items-center flex-col gap-y-4"> <div className="flex items-center flex-col gap-y-4">
<div className="flex gap-x-1"> <div className="flex gap-x-1">
@ -292,7 +292,7 @@ export default function MultiUserAuth() {
{customAppName || "AnythingLLM"} {customAppName || "AnythingLLM"}
</p> </p>
</div> </div>
<p className="text-sm text-white/90 text-center"> <p className="text-sm text-theme-text-secondary text-center">
{t("login.sign-in.start")} {customAppName || "AnythingLLM"}{" "} {t("login.sign-in.start")} {customAppName || "AnythingLLM"}{" "}
{t("login.sign-in.end")} {t("login.sign-in.end")}
</p> </p>
@ -305,7 +305,7 @@ export default function MultiUserAuth() {
name="username" name="username"
type="text" type="text"
placeholder={t("login.multi-user.placeholder-username")} placeholder={t("login.multi-user.placeholder-username")}
className="bg-zinc-900 text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-md p-2.5 w-full h-[48px] md:w-[300px] md:h-[34px]" className="bg-theme-settings-input-bg text-theme-text-primary placeholder:text-theme-settings-input-placeholder focus:outline-primary-button active:outline-primary-button outline-none text-sm rounded-md p-2.5 w-full h-[48px] md:w-[300px] md:h-[34px]"
required={true} required={true}
autoComplete="off" autoComplete="off"
/> />
@ -315,7 +315,7 @@ export default function MultiUserAuth() {
name="password" name="password"
type="password" type="password"
placeholder={t("login.multi-user.placeholder-password")} placeholder={t("login.multi-user.placeholder-password")}
className="bg-zinc-900 text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-md p-2.5 w-full h-[48px] md:w-[300px] md:h-[34px]" className="bg-theme-settings-input-bg text-theme-text-primary placeholder:text-theme-settings-input-placeholder focus:outline-primary-button active:outline-primary-button outline-none text-sm rounded-md p-2.5 w-full h-[48px] md:w-[300px] md:h-[34px]"
required={true} required={true}
autoComplete="off" autoComplete="off"
/> />

View File

@ -70,7 +70,7 @@ export default function SingleUserAuth() {
return ( return (
<> <>
<form onSubmit={handleLogin}> <form onSubmit={handleLogin}>
<div className="flex flex-col justify-center items-center relative rounded-2xl md:bg-login-gradient md:shadow-[0_4px_14px_rgba(0,0,0,0.25)] md:px-12 py-12 -mt-36 md:-mt-10"> <div className="flex flex-col justify-center items-center relative rounded-2xl bg-theme-bg-secondary md:shadow-[0_4px_14px_rgba(0,0,0,0.25)] md:px-12 py-12 -mt-36 md:-mt-10">
<div className="flex items-start justify-between pt-11 pb-9 rounded-t"> <div className="flex items-start justify-between pt-11 pb-9 rounded-t">
<div className="flex items-center flex-col gap-y-4"> <div className="flex items-center flex-col gap-y-4">
<div className="flex gap-x-1"> <div className="flex gap-x-1">
@ -81,7 +81,7 @@ export default function SingleUserAuth() {
{customAppName || "AnythingLLM"} {customAppName || "AnythingLLM"}
</p> </p>
</div> </div>
<p className="text-sm text-white/90 text-center"> <p className="text-sm text-theme-text-secondary text-center">
{t("login.sign-in.start")} {customAppName || "AnythingLLM"}{" "} {t("login.sign-in.start")} {customAppName || "AnythingLLM"}{" "}
{t("login.sign-in.end")} {t("login.sign-in.end")}
</p> </p>
@ -94,12 +94,11 @@ export default function SingleUserAuth() {
name="password" name="password"
type="password" type="password"
placeholder="Password" placeholder="Password"
className="bg-zinc-900 text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-md p-2.5 w-full h-[48px] md:w-[300px] md:h-[34px]" className="bg-theme-settings-input-bg text-theme-text-primary placeholder:text-theme-settings-input-placeholder focus:outline-primary-button active:outline-primary-button outline-none text-sm rounded-md p-2.5 w-full h-[48px] md:w-[300px] md:h-[34px]"
required={true} required={true}
autoComplete="off" autoComplete="off"
/> />
</div> </div>
{error && <p className="text-red-400 text-sm">Error: {error}</p>} {error && <p className="text-red-400 text-sm">Error: {error}</p>}
</div> </div>
</div> </div>
@ -109,13 +108,13 @@ export default function SingleUserAuth() {
type="submit" type="submit"
className="md:text-primary-button md:bg-transparent text-dark-text text-sm font-bold focus:ring-4 focus:outline-none rounded-md border-[1.5px] border-primary-button md:h-[34px] h-[48px] md:hover:text-white md:hover:bg-primary-button bg-primary-button focus:z-10 w-full" className="md:text-primary-button md:bg-transparent text-dark-text text-sm font-bold focus:ring-4 focus:outline-none rounded-md border-[1.5px] border-primary-button md:h-[34px] h-[48px] md:hover:text-white md:hover:bg-primary-button bg-primary-button focus:z-10 w-full"
> >
{loading ? "Validating..." : "Login"} {loading ? t("login.multi-user.validating") : t("login.multi-user.login")}
</button> </button>
</div> </div>
</div> </div>
</form> </form>
<ModalWrapper isOpen={isRecoveryCodeModalOpen}> <ModalWrapper isOpen={isRecoveryCodeModalOpen} noPortal={true}>
<RecoveryCodeModal <RecoveryCodeModal
recoveryCodes={recoveryCodes} recoveryCodes={recoveryCodes}
onDownloadComplete={handleDownloadComplete} onDownloadComplete={handleDownloadComplete}

View File

@ -13,7 +13,7 @@ import illustration from "@/media/illustrations/login-illustration.svg";
export default function PasswordModal({ mode = "single" }) { export default function PasswordModal({ mode = "single" }) {
const { loginLogo } = useLogo(); const { loginLogo } = useLogo();
return ( return (
<div className="fixed top-0 left-0 right-0 z-50 w-full overflow-x-hidden overflow-y-auto md:inset-0 h-[calc(100%-1rem)] h-full bg-[#25272C] flex flex-col md:flex-row items-center justify-center"> <div className="fixed top-0 left-0 right-0 z-50 w-full overflow-x-hidden overflow-y-auto md:inset-0 h-[calc(100%-1rem)] h-full bg-theme-bg-primary flex flex-col md:flex-row items-center justify-center">
<div <div
style={{ style={{
background: ` background: `
@ -33,13 +33,13 @@ export default function PasswordModal({ mode = "single" }) {
alt="login illustration" alt="login illustration"
/> />
</div> </div>
<div className="flex flex-col items-center justify-center h-full w-full md:w-1/2 z-50 relative -mt-20"> <div className="flex flex-col items-center justify-center h-full w-full md:w-1/2 z-50 relative md:-mt-20 mt-0 bg-theme-bg-secondary md:bg-transparent">
<img <img
src={loginLogo} src={loginLogo}
alt="Logo" alt="Logo"
className={`hidden relative md:flex rounded-2xl w-fit m-4 z-30 ${ className={`hidden relative md:flex rounded-2xl w-fit m-4 z-30 ${
mode === "single" ? "md:top-2" : "md:top-12" mode === "single" ? "md:top-2" : "md:top-12"
} absolute max-h-[65px] md:bg-login-gradient md:shadow-[0_4px_14px_rgba(0,0,0,0.25)]`} } absolute max-h-[65px]`}
style={{ objectFit: "contain" }} style={{ objectFit: "contain" }}
/> />
{mode === "single" ? <SingleUserAuth /> : <MultiUserAuth />} {mode === "single" ? <SingleUserAuth /> : <MultiUserAuth />}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 10 KiB