[feature] Nicer login.html page, with cute styling + link to source code (#19)
Fixes #9 - Cute styling, combination of Mastodon and GTS - Short description of the project - Error and status messages (temporarily) appear in disabled button with correct ARIA attributes - Sufficient contrast (WCAG AAA) Let me know if using `login.scss` both as an index file and for adding custom styling is okay. I figured this might be preferred over creating an extra folder and file. Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/19 Co-authored-by: vyxen <vyxen@tutamail.com> Co-committed-by: vyxen <vyxen@tutamail.com>
This commit is contained in:
8
app/javascript/flavours/glitch/packs/login.js
Normal file
8
app/javascript/flavours/glitch/packs/login.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import 'packs/public-path';
|
||||||
|
import { start } from '@rails/ujs';
|
||||||
|
import 'flavours/glitch/styles/login.scss';
|
||||||
|
|
||||||
|
start();
|
||||||
|
|
||||||
|
// This ensures that webpack compiles our images.
|
||||||
|
require.context('../images', true);
|
||||||
118
app/javascript/flavours/glitch/styles/login.scss
Normal file
118
app/javascript/flavours/glitch/styles/login.scss
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
@import 'variables';
|
||||||
|
@import 'styles/fonts/roboto';
|
||||||
|
@import 'styles/fonts/roboto-mono';
|
||||||
|
@import 'reset';
|
||||||
|
@import 'basics';
|
||||||
|
|
||||||
|
body {
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #89caff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
max-width: 30rem;
|
||||||
|
padding: 1rem;
|
||||||
|
margin: auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mascot {
|
||||||
|
height: 10rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
flex-direction: column;
|
||||||
|
row-gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
column-gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instance {
|
||||||
|
background: #282c37;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #9baec8;
|
||||||
|
display: block;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 18px;
|
||||||
|
margin: 0;
|
||||||
|
outline: 0;
|
||||||
|
padding: 15px;
|
||||||
|
padding-inline-end: 30px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: flex;
|
||||||
|
column-gap: .5rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: #66befe;
|
||||||
|
border: 0 none;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #2a2b2f;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
line-height: 22px;
|
||||||
|
font-family: inherit;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 7px 10px;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
flex-basis: auto;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #89caff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background-color: #9baec8;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
background-color: #444b5d;
|
||||||
|
padding: 15px;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
row-gap: .75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-footer {
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
p, a {
|
||||||
|
color: #97A8B4;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,9 @@ pack:
|
|||||||
- flavours/glitch/async/getting_started
|
- flavours/glitch/async/getting_started
|
||||||
- flavours/glitch/async/home_timeline
|
- flavours/glitch/async/home_timeline
|
||||||
- flavours/glitch/async/notifications
|
- flavours/glitch/async/notifications
|
||||||
|
login:
|
||||||
|
filename: packs/login.js
|
||||||
|
stylesheet: true
|
||||||
mailer:
|
mailer:
|
||||||
modal:
|
modal:
|
||||||
public: packs/public.jsx
|
public: packs/public.jsx
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ async function auth() {
|
|||||||
|
|
||||||
const domain = matches[2];
|
const domain = matches[2];
|
||||||
if (!domain) {
|
if (!domain) {
|
||||||
setMessage('Invalid instance', false);
|
setMessage('Invalid instance', true);
|
||||||
|
await new Promise(r => setTimeout(r, 2000));
|
||||||
|
setMessage('Authorize', false, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
localStorage.setItem('domain', domain);
|
localStorage.setItem('domain', domain);
|
||||||
@@ -92,7 +94,6 @@ async function getToken(code, domain) {
|
|||||||
formData.append('scope', 'read write follow push');
|
formData.append('scope', 'read write follow push');
|
||||||
formData.append('redirect_uri', document.location.origin + document.location.pathname);
|
formData.append('redirect_uri', document.location.origin + document.location.pathname);
|
||||||
|
|
||||||
|
|
||||||
// eslint-disable-next-line promise/catch-or-return
|
// eslint-disable-next-line promise/catch-or-return
|
||||||
return fetch(tokenUrl, {
|
return fetch(tokenUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -108,7 +109,14 @@ async function getToken(code, domain) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function setMessage(message, disabled = true) {
|
function setMessage(message, error = false, disabled = true) {
|
||||||
|
document.getElementById('message').setAttribute('role', 'status');
|
||||||
document.getElementById('message').textContent = message;
|
document.getElementById('message').textContent = message;
|
||||||
document.getElementById('btn').disabled = disabled;
|
document.getElementById('btn').disabled = disabled;
|
||||||
|
|
||||||
|
if (!error) return;
|
||||||
|
|
||||||
|
const instance = document.getElementById('instance');
|
||||||
|
instance.setAttribute('aria-invalid', true);
|
||||||
|
instance.setAttribute('aria-describedby', 'message');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,50 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Login | Masto-FE (🦥 flavour)</title>
|
<title>Login | Masto-FE (🦥 flavour)</title>
|
||||||
|
<meta content="width=device-width, initial-scale=1" name="viewport">
|
||||||
|
<link rel="stylesheet" media="all" href="/packs/css/core/common.css" />
|
||||||
|
<link rel="stylesheet" media="all" href="/packs/css/flavours/glitch/login.css" />
|
||||||
<script src="/auth.js"></script>
|
<script src="/auth.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<input type="text" id="instance" placeholder="yourinstance.tld">
|
<div class="login-container">
|
||||||
<button onclick="auth()" id="btn">Log in</button>
|
<header>
|
||||||
<span id="message"></span>
|
<img class="mascot" alt src="images/mascot.svg" />
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<div class="login">
|
||||||
|
<input class="instance" id="instance" placeholder="Instance URL" aria-label="Instance URL" value="" onkeypress="if (event.keyCode == 13) auth()">
|
||||||
|
<button type="submit" class="button" id="btn" onclick="auth()">
|
||||||
|
<span id="message">Authorize</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<p>
|
||||||
|
This is a standalone version of the Mastodon front-end that offers compatibility with GoToSocial instances. It is based
|
||||||
|
on <a href="https://iceshrimp.dev/iceshrimp/masto-fe-standalone" rel="nofollow">Iceshrimp's Masto-FE Standalone</a>,
|
||||||
|
which is itself a fork of <a href="https://github.com/glitch-soc/mastodon" rel="nofollow">Mastodon Glitch Edition</a>,
|
||||||
|
which in turn forks <a href="https://github.com/mastodon/mastodon/" rel="nofollow">Mastodon</a>. Phew!
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The application is completely client-side, meaning everything happens in the browser on your machine. It does not store
|
||||||
|
information anywhere else than your browser's local storage.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<footer class="link-footer">
|
||||||
|
<p>
|
||||||
|
<strong>Masto-FE (🦥 flavour)</strong>
|
||||||
|
<span aria-hidden="true"> · </span>
|
||||||
|
<a href="https://codeberg.org/superseriousbusiness/masto-fe-standalone" rel="noopener noreferrer" target="_blank">
|
||||||
|
Source code
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user