feat(login): new login screen design

This commit is contained in:
trashtemp 2021-12-25 16:01:19 +01:00
parent d7f52fb6f4
commit 5c59f187bd
No known key found for this signature in database
GPG key ID: D1F0DB65081B0FC6
9 changed files with 300 additions and 114 deletions

2
external/lang vendored

@ -1 +1 @@
Subproject commit 697960e42a5e27947a1b8d7338b406ae5a9372dd
Subproject commit 0bac1d588e7bdf47cdc5659abbbbc75dfb75fd37

View file

@ -46,7 +46,13 @@ $fontSize: 40px;
@while ($count > 0) {
$left: random(100);
$deltaLeft: random(2 * $windNoise * 10) / 10 - $windNoise + $windSpeed;
/*$deltaLeft: math.div(random(2 * $windNoise * 10), 10) -
$windNoise +
$windSpeed;*/
$scale: 1 + (random(2 * $sizeNoise * 10) / 10 - $sizeNoise) / 100;
/*$scale: 1 +
(math.div(random(2 * $sizeNoise * 10), 10) - $sizeNoise) /
100;*/
.snowflake:nth-child(#{$count}) {
animation: animation-snowflake-#{$count} linear infinite;

View file

@ -1,78 +1,168 @@
.login {
width: 100%;
height: 100%;
padding: 40px 35px;
display: flex;
flex-direction: row;
user-select: none;
svg {
margin: auto;
}
background: url("/src/pages/login/background.jpg");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
> div {
flex: 1;
.nav {
display: flex;
align-items: center;
.logo {
flex-grow: 1;
> img {
height: 24px;
}
}
}
.content {
display: flex;
flex-direction: column;
justify-content: space-between;
flex-grow: 1;
}
.attribution {
color: var(--tertiary-background);
font-size: 12px;
line-height: 12px;
margin: 8px;
select {
max-width: 180px;
padding: 4px;
height: fit-content;
background-color: rgba(36, 36, 36, 0.75);
border: 2px solid rgba(128, 128, 128, 0.15);
backdrop-filter: blur(20px);
font-size: 13px;
}
display: flex;
flex-direction: row;
justify-content: space-between;
}
.middle {
display: flex;
gap: 50px;
.modal {
display: flex;
flex-direction: row;
justify-content: center;
.loginQR {
background-color: rgba(36, 36, 36, 0.75);
border: 2px solid rgba(128, 128, 128, 0.15);
border-radius: 8px;
width: 330px;
}
}
.bg {
background-size: cover !important;
}
}
.form {
background-color: rgba(36, 36, 36, 0.75);
border: 2px solid rgba(128, 128, 128, 0.15);
backdrop-filter: blur(20px);
max-width: 330px;
max-height: 600px;
padding: 30px 25px;
border-radius: 8px;
margin-inline-start: 50px;
margin-top: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px 0 rgb(0 0 0 / 20%);
.form {
display: flex;
flex-direction: column;
font-size: 14px;
.formModal {
display: flex;
flex-direction: column;
gap: 10px;
img {
width: 260px;
margin: auto;
> span {
font-size: 13px;
b {
font-weight: 600;
}
}
.welcome {
font-size: 20px;
font-weight: 600;
margin-bottom: 10px;
}
.subtitle {
font-weight: 400;
font-size: 14px;
}
form {
display: flex;
flex-direction: column;
gap: 10px;
> div {
margin: 0;
margin-bottom: -4px;
font-size: 12px;
color: var(--secondary-foreground);
}
input {
background: var(--secondary-background);
/*border: 2px solid rgba(128, 128, 128, 0.15);*/
}
button {
padding: 8px;
background: var(--secondary-background);
margin-bottom: 15px;
}
}
}
}
a {
margin-top: 4px;
}
color: white;
form {
margin: 1em 0;
display: flex;
flex-direction: column;
button {
margin-top: 24px;
&:hover {
text-decoration: underline;
}
}
.create {
text-align: center;
color: var(--tertiary-foreground);
.bottom {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
a {
margin: 0 4px;
.links {
display: flex;
align-items: center;
gap: 15px;
.socials {
display: flex;
gap: 10px;
a {
transition: opacity 0.2s ease-in-out;
&:hover {
opacity: 0.7;
}
&:active {
opacity: 0.5;
}
}
}
.bullet {
height: 5px;
width: 5px;
background: grey;
border-radius: 50%;
}
.revolt {
display: flex;
gap: 10px;
a {
color: white !important;
}
}
}
}
}
@ -103,24 +193,46 @@
}
}
.footer {
margin-top: 12px;
text-align: center;
color: var(--tertiary6);
@media only screen and (max-width: 768px) {
.login {
padding: 30px 20px;
background-image: unset;
background-color: var(--primary-background);
a {
color: var(--tertiary-background) !important;
cursor: pointer;
margin: 0 2px;
.content {
.nav {
.logo {
img {
height: 24px;
}
}
}
&:hover {
color: var(--tertiary-foreground) !important;
.bottom {
flex-direction: column;
.links {
flex-direction: column;
gap: 10px;
}
.bullet,
.attribution {
display: none;
}
}
}
.form {
border: unset;
margin-inline-start: 0;
padding: 0;
max-width: unset;
box-shadow: unset;
}
.loginQR {
display: none;
}
}
}
@media only screen and (max-width: 768px) {
.bg {
display: none;
}
}

View file

@ -1,3 +1,4 @@
import { Twitter, Github, Mastodon } from "@styled-icons/boxicons-logos";
import { observer } from "mobx-react-lite";
import { Helmet } from "react-helmet";
import { Route, Switch } from "react-router-dom";
@ -8,6 +9,7 @@ import { Text } from "preact-i18n";
import { useApplicationState } from "../../mobx/State";
import wideSVG from "../../../public/assets/wide.svg";
import LocaleSelector from "../../components/common/LocaleSelector";
import background from "./background.jpg";
@ -36,14 +38,104 @@ export default observer(() => {
/>
</Helmet>
<div className={styles.content}>
<div className={styles.attribution}>
<div className={styles.nav}>
<a className={styles.logo}>
<img
src="https://app.revolt.chat/assets/wide.fe712d4a.svg"
draggable={false}
/>
</a>
<LocaleSelector />
</div>
{/*<div className={styles.middle}>*/}
<div className={styles.form}>
{/*<div style={styles.version}>
API: <code>{configuration?.revolt ?? "???"}</code>{" "}
&middot; revolt.js: <code>{LIBRARY_VERSION}</code>{" "}
&middot; App: <code>{APP_VERSION}</code>
</div>*/}
<Switch>
<Route path="/login/create">
<FormCreate />
</Route>
<Route path="/login/resend">
<FormResend />
</Route>
<Route path="/login/verify/:token">
<FormVerify />
</Route>
<Route path="/login/reset/:token">
<FormReset />
</Route>
<Route path="/login/reset">
<FormSendReset />
</Route>
<Route path="/">
<FormLogin />
</Route>
</Switch>
</div>
{/*<div className={styles.loginQR}></div>*/}
{/*</div>*/}
<div className={styles.bottom}>
<div className={styles.links}>
<div className={styles.socials}>
<a
href="https://github.com/revoltchat"
target="_blank">
<Github size={24} />
</a>
<a
href="https://twitter.com/revoltchat"
target="_blank">
<Twitter size={24} />
</a>
<a
href="https://mastodon.social/@revoltchat"
target="_blank">
<Mastodon size={24} />
</a>
</div>
<div className={styles.bullet} />
<div className={styles.revolt}>
<a
href="https://revolt.chat/about"
target="_blank"
rel="noreferrer">
<Text id="general.about" />
</a>
<a
href="https://revolt.chat/terms"
target="_blank"
rel="noreferrer">
<Text id="general.tos" />
</a>
<a
href="https://revolt.chat/privacy"
target="_blank"
rel="noreferrer">
<Text id="general.privacy" />
</a>
</div>
</div>
<a
className={styles.attribution}
href="https://unsplash.com/@fakurian"
target="_blank">
<Text id="general.image_by" /> &lrm;@fakurian &rlm;·
unsplash.com
</a>
</div>
{/*<div className={styles.attribution}>
<span>
API: <code>{configuration?.revolt ?? "???"}</code>{" "}
&middot; revolt.js: <code>{LIBRARY_VERSION}</code>{" "}
&middot; App: <code>{APP_VERSION}</code>
</span>
<span>
<LocaleSelector />
</span>
</div>
<div className={styles.modal}>
@ -67,18 +159,8 @@ export default observer(() => {
<FormLogin />
</Route>
</Switch>
</div>
<div className={styles.attribution}>
<span>
<Text id="general.image_by" /> &lrm;@lorenzoherrera
&rlm;· unsplash.com
</span>
</div>
</div>*/}
</div>
<div
className={styles.bg}
style={{ background: `url('${background}')` }}
/>
</div>
</>
);

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 484 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View file

@ -18,7 +18,6 @@ import Preloader from "../../../components/ui/Preloader";
import FormField from "../FormField";
import { CaptchaBlock, CaptchaProps } from "./CaptchaBlock";
import { Legal } from "./Legal";
import { MailProvider } from "./MailProvider";
interface Props {
@ -144,8 +143,16 @@ export function Form({ page, callback }: Props) {
if (loading) return <Preloader type="spinner" />;
return (
<div className={styles.form}>
<img src={wideSVG} />
<div className={styles.formModal}>
<div className={styles.welcome}>
<div className={styles.title}>
<Text id="login.welcome" />
</div>
<div className={styles.subtitle}>
<Text id="login.subtitle" />
</div>
</div>
{/* Preact / React typing incompatabilities */}
<form
onSubmit={
@ -203,13 +210,17 @@ export function Form({ page, callback }: Props) {
{page === "create" && (
<>
<span className={styles.create}>
<Text id="login.existing" />
<b>
<Text id="login.existing" />
</b>{" "}
<Link to="/login">
<Text id="login.title" />
</Link>
</span>
<span className={styles.create}>
<Text id="login.missing_verification" />
<b>
<Text id="login.missing_verification" />
</b>{" "}
<Link to="/login/resend">
<Text id="login.resend" />
</Link>
@ -219,13 +230,17 @@ export function Form({ page, callback }: Props) {
{page === "login" && (
<>
<span className={styles.create}>
<Text id="login.new" />
<b>
<Text id="login.new" />
</b>{" "}
<Link to="/login/create">
<Text id="login.create" />
</Link>
</span>
<span className={styles.create}>
<Text id="login.forgot" />
<b>
<Text id="login.forgot" />
</b>{" "}
<Link to="/login/reset">
<Text id="login.reset" />
</Link>
@ -243,7 +258,6 @@ export function Form({ page, callback }: Props) {
</span>
</>
)}
<Legal />
</div>
);
}

View file

@ -1,29 +0,0 @@
import styles from "../Login.module.scss";
import { Text } from "preact-i18n";
export function Legal() {
return (
<span className={styles.footer}>
<a
href="https://revolt.chat/about"
target="_blank"
rel="noreferrer">
<Text id="general.about" />
</a>
&middot;
<a
href="https://revolt.chat/terms"
target="_blank"
rel="noreferrer">
<Text id="general.tos" />
</a>
&middot;
<a
href="https://revolt.chat/privacy"
target="_blank"
rel="noreferrer">
<Text id="general.privacy" />
</a>
</span>
);
}

View file

@ -126,6 +126,7 @@ export const Overview = observer(({ server }: Props) => {
alignItems: "center",
}}>
<span style={{ flexShrink: "0", flex: `25%` }}>{i18n}</span>
<span>Sends a message when someone joins your server</span>
<ComboBox
value={
systemMessages?.[