mirror of
https://github.com/revoltchat/revite.git
synced 2024-12-26 15:32:11 -05:00
feat(login): new login screen design
This commit is contained in:
parent
d7f52fb6f4
commit
5c59f187bd
9 changed files with 300 additions and 114 deletions
2
external/lang
vendored
2
external/lang
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 697960e42a5e27947a1b8d7338b406ae5a9372dd
|
Subproject commit 0bac1d588e7bdf47cdc5659abbbbc75dfb75fd37
|
|
@ -46,7 +46,13 @@ $fontSize: 40px;
|
||||||
@while ($count > 0) {
|
@while ($count > 0) {
|
||||||
$left: random(100);
|
$left: random(100);
|
||||||
$deltaLeft: random(2 * $windNoise * 10) / 10 - $windNoise + $windSpeed;
|
$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 + (random(2 * $sizeNoise * 10) / 10 - $sizeNoise) / 100;
|
||||||
|
/*$scale: 1 +
|
||||||
|
(math.div(random(2 * $sizeNoise * 10), 10) - $sizeNoise) /
|
||||||
|
100;*/
|
||||||
|
|
||||||
.snowflake:nth-child(#{$count}) {
|
.snowflake:nth-child(#{$count}) {
|
||||||
animation: animation-snowflake-#{$count} linear infinite;
|
animation: animation-snowflake-#{$count} linear infinite;
|
||||||
|
|
|
@ -1,78 +1,168 @@
|
||||||
.login {
|
.login {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
padding: 40px 35px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
user-select: none;
|
||||||
|
|
||||||
svg {
|
background: url("/src/pages/login/background.jpg");
|
||||||
margin: auto;
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
flex-grow: 1;
|
||||||
|
> img {
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> div {
|
|
||||||
flex: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.attribution {
|
select {
|
||||||
color: var(--tertiary-background);
|
max-width: 180px;
|
||||||
font-size: 12px;
|
padding: 4px;
|
||||||
line-height: 12px;
|
height: fit-content;
|
||||||
margin: 8px;
|
background-color: rgba(36, 36, 36, 0.75);
|
||||||
|
border: 2px solid rgba(128, 128, 128, 0.15);
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.middle {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
gap: 50px;
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal {
|
.loginQR {
|
||||||
display: flex;
|
background-color: rgba(36, 36, 36, 0.75);
|
||||||
flex-direction: row;
|
border: 2px solid rgba(128, 128, 128, 0.15);
|
||||||
|
border-radius: 8px;
|
||||||
justify-content: center;
|
width: 330px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg {
|
.form {
|
||||||
background-size: cover !important;
|
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 {
|
.formModal {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
font-size: 14px;
|
gap: 10px;
|
||||||
|
|
||||||
img {
|
> span {
|
||||||
width: 260px;
|
font-size: 13px;
|
||||||
margin: auto;
|
|
||||||
|
b {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
.welcome {
|
||||||
margin-top: 4px;
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form {
|
form {
|
||||||
margin: 1em 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
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 {
|
button {
|
||||||
margin-top: 24px;
|
padding: 8px;
|
||||||
|
background: var(--secondary-background);
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.create {
|
|
||||||
text-align: center;
|
|
||||||
color: var(--tertiary-foreground);
|
|
||||||
|
|
||||||
a {
|
a {
|
||||||
margin: 0 4px;
|
color: white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
.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);
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--tertiary-background) !important;
|
|
||||||
cursor: pointer;
|
|
||||||
margin: 0 2px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: var(--tertiary-foreground) !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 768px) {
|
@media only screen and (max-width: 768px) {
|
||||||
.bg {
|
.login {
|
||||||
|
padding: 30px 20px;
|
||||||
|
background-image: unset;
|
||||||
|
background-color: var(--primary-background);
|
||||||
|
|
||||||
|
.content {
|
||||||
|
.nav {
|
||||||
|
.logo {
|
||||||
|
img {
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom {
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.links {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bullet,
|
||||||
|
.attribution {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form {
|
||||||
|
border: unset;
|
||||||
|
margin-inline-start: 0;
|
||||||
|
padding: 0;
|
||||||
|
max-width: unset;
|
||||||
|
box-shadow: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loginQR {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Twitter, Github, Mastodon } from "@styled-icons/boxicons-logos";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
import { Route, Switch } from "react-router-dom";
|
import { Route, Switch } from "react-router-dom";
|
||||||
|
@ -8,6 +9,7 @@ import { Text } from "preact-i18n";
|
||||||
|
|
||||||
import { useApplicationState } from "../../mobx/State";
|
import { useApplicationState } from "../../mobx/State";
|
||||||
|
|
||||||
|
import wideSVG from "../../../public/assets/wide.svg";
|
||||||
import LocaleSelector from "../../components/common/LocaleSelector";
|
import LocaleSelector from "../../components/common/LocaleSelector";
|
||||||
import background from "./background.jpg";
|
import background from "./background.jpg";
|
||||||
|
|
||||||
|
@ -36,14 +38,104 @@ export default observer(() => {
|
||||||
/>
|
/>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div className={styles.content}>
|
<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>{" "}
|
||||||
|
· revolt.js: <code>{LIBRARY_VERSION}</code>{" "}
|
||||||
|
· 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" /> ‎@fakurian ‏·
|
||||||
|
unsplash.com
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{/*<div className={styles.attribution}>
|
||||||
<span>
|
<span>
|
||||||
API: <code>{configuration?.revolt ?? "???"}</code>{" "}
|
API: <code>{configuration?.revolt ?? "???"}</code>{" "}
|
||||||
· revolt.js: <code>{LIBRARY_VERSION}</code>{" "}
|
· revolt.js: <code>{LIBRARY_VERSION}</code>{" "}
|
||||||
· App: <code>{APP_VERSION}</code>
|
· App: <code>{APP_VERSION}</code>
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<LocaleSelector />
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.modal}>
|
<div className={styles.modal}>
|
||||||
|
@ -67,18 +159,8 @@ export default observer(() => {
|
||||||
<FormLogin />
|
<FormLogin />
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
</div>*/}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.attribution}>
|
|
||||||
<span>
|
|
||||||
<Text id="general.image_by" /> ‎@lorenzoherrera
|
|
||||||
‏· unsplash.com
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={styles.bg}
|
|
||||||
style={{ background: `url('${background}')` }}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
BIN
src/pages/login/background-old.jpg
Normal file
BIN
src/pages/login/background-old.jpg
Normal file
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 |
|
@ -18,7 +18,6 @@ import Preloader from "../../../components/ui/Preloader";
|
||||||
|
|
||||||
import FormField from "../FormField";
|
import FormField from "../FormField";
|
||||||
import { CaptchaBlock, CaptchaProps } from "./CaptchaBlock";
|
import { CaptchaBlock, CaptchaProps } from "./CaptchaBlock";
|
||||||
import { Legal } from "./Legal";
|
|
||||||
import { MailProvider } from "./MailProvider";
|
import { MailProvider } from "./MailProvider";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -144,8 +143,16 @@ export function Form({ page, callback }: Props) {
|
||||||
if (loading) return <Preloader type="spinner" />;
|
if (loading) return <Preloader type="spinner" />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.form}>
|
<div className={styles.formModal}>
|
||||||
<img src={wideSVG} />
|
<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 */}
|
{/* Preact / React typing incompatabilities */}
|
||||||
<form
|
<form
|
||||||
onSubmit={
|
onSubmit={
|
||||||
|
@ -203,13 +210,17 @@ export function Form({ page, callback }: Props) {
|
||||||
{page === "create" && (
|
{page === "create" && (
|
||||||
<>
|
<>
|
||||||
<span className={styles.create}>
|
<span className={styles.create}>
|
||||||
|
<b>
|
||||||
<Text id="login.existing" />
|
<Text id="login.existing" />
|
||||||
|
</b>{" "}
|
||||||
<Link to="/login">
|
<Link to="/login">
|
||||||
<Text id="login.title" />
|
<Text id="login.title" />
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
<span className={styles.create}>
|
<span className={styles.create}>
|
||||||
|
<b>
|
||||||
<Text id="login.missing_verification" />
|
<Text id="login.missing_verification" />
|
||||||
|
</b>{" "}
|
||||||
<Link to="/login/resend">
|
<Link to="/login/resend">
|
||||||
<Text id="login.resend" />
|
<Text id="login.resend" />
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -219,13 +230,17 @@ export function Form({ page, callback }: Props) {
|
||||||
{page === "login" && (
|
{page === "login" && (
|
||||||
<>
|
<>
|
||||||
<span className={styles.create}>
|
<span className={styles.create}>
|
||||||
|
<b>
|
||||||
<Text id="login.new" />
|
<Text id="login.new" />
|
||||||
|
</b>{" "}
|
||||||
<Link to="/login/create">
|
<Link to="/login/create">
|
||||||
<Text id="login.create" />
|
<Text id="login.create" />
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
<span className={styles.create}>
|
<span className={styles.create}>
|
||||||
|
<b>
|
||||||
<Text id="login.forgot" />
|
<Text id="login.forgot" />
|
||||||
|
</b>{" "}
|
||||||
<Link to="/login/reset">
|
<Link to="/login/reset">
|
||||||
<Text id="login.reset" />
|
<Text id="login.reset" />
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -243,7 +258,6 @@ export function Form({ page, callback }: Props) {
|
||||||
</span>
|
</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Legal />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
|
||||||
·
|
|
||||||
<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>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -126,6 +126,7 @@ export const Overview = observer(({ server }: Props) => {
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
}}>
|
}}>
|
||||||
<span style={{ flexShrink: "0", flex: `25%` }}>{i18n}</span>
|
<span style={{ flexShrink: "0", flex: `25%` }}>{i18n}</span>
|
||||||
|
<span>Sends a message when someone joins your server</span>
|
||||||
<ComboBox
|
<ComboBox
|
||||||
value={
|
value={
|
||||||
systemMessages?.[
|
systemMessages?.[
|
||||||
|
|
Loading…
Reference in a new issue