mirror of
https://github.com/revoltchat/revite.git
synced 2024-12-25 23:22:06 -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) {
|
||||
$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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
.nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.logo {
|
||||
flex-grow: 1;
|
||||
> img {
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.middle {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
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 {
|
||||
.formModal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 14px;
|
||||
gap: 10px;
|
||||
|
||||
img {
|
||||
width: 260px;
|
||||
margin: auto;
|
||||
> span {
|
||||
font-size: 13px;
|
||||
|
||||
b {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
margin-top: 4px;
|
||||
.welcome {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
form {
|
||||
margin: 1em 0;
|
||||
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 {
|
||||
margin-top: 24px;
|
||||
padding: 8px;
|
||||
background: var(--secondary-background);
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.create {
|
||||
text-align: center;
|
||||
color: var(--tertiary-foreground);
|
||||
|
||||
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) {
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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 { 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>{" "}
|
||||
· 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>
|
||||
API: <code>{configuration?.revolt ?? "???"}</code>{" "}
|
||||
· revolt.js: <code>{LIBRARY_VERSION}</code>{" "}
|
||||
· 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>
|
||||
<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>
|
||||
</>
|
||||
);
|
||||
|
|
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 { 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}>
|
||||
<b>
|
||||
<Text id="login.existing" />
|
||||
</b>{" "}
|
||||
<Link to="/login">
|
||||
<Text id="login.title" />
|
||||
</Link>
|
||||
</span>
|
||||
<span className={styles.create}>
|
||||
<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}>
|
||||
<b>
|
||||
<Text id="login.new" />
|
||||
</b>{" "}
|
||||
<Link to="/login/create">
|
||||
<Text id="login.create" />
|
||||
</Link>
|
||||
</span>
|
||||
<span className={styles.create}>
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
}}>
|
||||
<span style={{ flexShrink: "0", flex: `25%` }}>{i18n}</span>
|
||||
<span>Sends a message when someone joins your server</span>
|
||||
<ComboBox
|
||||
value={
|
||||
systemMessages?.[
|
||||
|
|
Loading…
Reference in a new issue