Very basic initial UI implementation

main
Gabe Farrell 2 years ago
commit 5d57b4ae12

@ -0,0 +1,15 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier/skip-formatting'
],
parserOptions: {
ecmaVersion: 'latest'
}
}

28
.gitignore vendored

@ -0,0 +1,28 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"tabWidth": 2,
"singleQuote": true,
"printWidth": 100,
"trailingComma": "none"
}

@ -0,0 +1,8 @@
{
"recommendations": [
"Vue.volar",
"Vue.vscode-typescript-vue-plugin",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}

@ -0,0 +1,46 @@
# auth-ui
This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
## Type Support for `.vue` Imports in TS
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
1. Disable the built-in TypeScript Extension
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
## Customize configuration
See [Vite Configuration Reference](https://vitejs.dev/config/).
## Project Setup
```sh
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
```
### Type-Check, Compile and Minify for Production
```sh
npm run build
```
### Lint with [ESLint](https://eslint.org/)
```sh
npm run lint
```

1
env.d.ts vendored

@ -0,0 +1 @@
/// <reference types="vite/client" />

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

3636
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,34 @@
{
"name": "auth-ui",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"format": "prettier --write src/"
},
"dependencies": {
"vue": "^3.3.4",
"vue-router": "^4.2.5"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.3.3",
"@tsconfig/node18": "^18.2.2",
"@types/node": "^18.18.5",
"@vitejs/plugin-vue": "^4.4.0",
"@vue/eslint-config-prettier": "^8.0.0",
"@vue/eslint-config-typescript": "^12.0.0",
"@vue/tsconfig": "^0.4.0",
"eslint": "^8.49.0",
"eslint-plugin-vue": "^9.17.0",
"npm-run-all2": "^6.1.1",
"prettier": "^3.0.3",
"typescript": "~5.2.0",
"vite": "^4.4.11",
"vue-tsc": "^1.8.19"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@ -0,0 +1,10 @@
<script setup lang="ts">
import { RouterView } from 'vue-router'
</script>
<template>
<RouterView />
</template>
<style scoped>
</style>

@ -0,0 +1,82 @@
/* fonts */
@import url('https://fonts.googleapis.com/css2?family=Mulish:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,300;1,400;1,500;1,600;1,700;1,800&family=Roboto:wght@400;500&display=swap');
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-indigo: #2c3e50;
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}
:root {
--purple-soft: #EAE9F0;
--white-soft: #FBFBFB;
--purple: #1B0554;
--purple-light: #321e65;
--text-dark: #383445;
--text-body: #5E5673;
--text-body-light: #736C88;
--grey: #6E6781;
--grey-light: #C1BEC7;
--red: #F41F4E;
--yellow: #FFD43E;
--green: #40CE4E;
}
/* semantic color variables for this project */
:root {
--color-background: var(--purple-soft);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--text-dark);
--color-text: var(--text-body);
--color-drop-shadow: #d9d4e3;
--section-gap: 160px;
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
font-weight: normal;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition:
color 0.5s,
background-color 0.5s;
line-height: 1.6;
font-family:
'Mulish',
Inter,
sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1354 605"><title>Artboard 2</title><path d="M16.72,152.93c20.43,0,33.65-13.22,33.65-33.05V72.41h93.74v80.52H212v93.74h-67.9v63.7c0,47.47,6,60.09,30.65,60.09,10.81,0,22.23-2.41,37.25-6v88.93c-14.42,4.21-38.46,6-52.88,6C84.62,459.39,50.37,425.14,50.37,350V246.67H-.11V152.93Z" style="fill:#1B0554"/><path d="M372.27,146.92a112.26,112.26,0,0,1,76.92,30.65V152.93h93.74V453.38H449.19V426.94a106.5,106.5,0,0,1-76.92,32.45c-85.93,0-141.81-69.7-141.81-156.23C230.46,217.23,286.34,146.92,372.27,146.92ZM324.2,303.16c0,34.25,28.24,62.49,62.5,62.49a62.83,62.83,0,0,0,62.49-62.49c0-34.26-28.24-62.5-62.49-62.5A62.83,62.83,0,0,0,324.2,303.16Z" style="fill:#1B0554"/><path d="M815.17,518.57c58.21,0,105.75-12.82,105.75-65.79V426.94A106.5,106.5,0,0,1,844,459.39c-85.93,0-141.81-69.7-141.81-156.23,0-85.93,55.88-156.24,141.81-156.24a112.26,112.26,0,0,1,76.92,30.65V152.93h93.74V447.37c0,119.69-82,157.73-198.89,157.73Zm-59.46,37.86,40.22-253.27c0,34.25,28.24,62.49,62.5,62.49a62.83,62.83,0,0,0,62.49-62.49c0-34.26-28.24-62.5-62.49-62.5A62.83,62.83,0,0,0,795.93,303.16Z" style="fill:#1B0554"/><path d="M1354,303.16c0,85.93-69.7,156.23-156.23,156.23-85.93,0-156.24-70.3-156.24-156.23,0-86.53,70.31-156.24,156.24-156.24A155.92,155.92,0,0,1,1354,303.16Zm-156.23,62.49a62.83,62.83,0,0,0,62.49-62.49c0-34.26-28.24-62.5-62.49-62.5a62.83,62.83,0,0,0-62.5,62.5C1135.27,337.41,1163.51,365.65,1197.77,365.65Z" style="fill:#1B0554"/><path d="M780.57,604.6c-109.8,0-205.44-47.93-205.44-185.57V0h93.53V419c0,74.26,52,99.19,112.25,99.19Z" style="fill:#1B0554"/></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -0,0 +1,35 @@
@import './base.css';
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
height: 100vh;
}
input {
font-weight: 500;
font-size: 14px;
font-family: 'Mulish';
margin-bottom: 0.8em;
padding: 1em;
border: 2px solid var(--text-body-light);
border-radius: 5px;
color: var(--text-body);
background-color: var(--white-soft);
}
button {
font-family: 'Mulish';
border: none;
background-color: var(--purple);
color: var(--white-soft);
font-size: 14px;
font-weight: 500;
border-radius: 5px;
padding: 1em;
}
button:hover {
background-color: var(--purple-light);
cursor: pointer;
}

@ -0,0 +1,123 @@
<template>
<div class="soc-wrapper">
<button class="gsi-material-button">
<div class="gsi-material-button-state"></div>
<div class="gsi-material-button-content-wrapper">
<div class="gsi-material-button-icon">
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" class="mr-2" viewBox="0 0 1792 1792">
<path d="M896 128q209 0 385.5 103t279.5 279.5 103 385.5q0 251-146.5 451.5t-378.5 277.5q-27 5-40-7t-13-30q0-3 .5-76.5t.5-134.5q0-97-52-142 57-6 102.5-18t94-39 81-66.5 53-105 20.5-150.5q0-119-79-206 37-91-8-204-28-9-81 11t-92 44l-38 24q-93-26-192-26t-192 26q-16-11-42.5-27t-83.5-38.5-85-13.5q-45 113-8 204-79 87-79 206 0 85 20.5 150t52.5 105 80.5 67 94 39 102.5 18q-39 36-49 103-21 10-45 15t-57 5-65.5-21.5-55.5-62.5q-19-32-48.5-52t-49.5-24l-20-3q-21 0-29 4.5t-5 11.5 9 14 13 12l7 5q22 10 43.5 38t31.5 51l10 23q13 38 44 61.5t67 30 69.5 7 55.5-3.5l23-4q0 38 .5 88.5t.5 54.5q0 18-13 30t-40 7q-232-77-378.5-277.5t-146.5-451.5q0-209 103-385.5t279.5-279.5 385.5-103zm-477 1103q3-7-7-12-10-3-13 2-3 7 7 12 9 6 13-2zm31 34q7-5-2-16-10-9-16-3-7 5 2 16 10 10 16 3zm30 45q9-7 0-19-8-13-17-6-9 5 0 18t17 7zm42 42q8-8-4-19-12-12-20-3-9 8 4 19 12 12 20 3zm57 25q3-11-13-16-15-4-19 7t13 15q15 6 19-6zm63 5q0-13-17-11-16 0-16 11 0 13 17 11 16 0 16-11zm58-10q-2-11-18-9-16 3-14 15t18 8 14-14z"></path>
</svg>
</div>
<span class="gsi-material-button-contents">Sign in with GitHub</span>
<span style="display: none;">Sign in with GitHub</span>
</div>
</button>
</div>
</template>
<style scoped>
.soc-wrapper {
width: 100%;
}
.gsi-material-button {
display: block;
margin: 0px auto;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-webkit-appearance: none;
background-color: WHITE;
background-image: none;
border: 1px solid var(--grey-light);
-webkit-border-radius: 5px;
border-radius: 5px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: #1f1f1f;
cursor: pointer;
font-family: 'Roboto', arial, sans-serif;
font-size: 14px;
height: 46px;
letter-spacing: 0.25px;
outline: none;
overflow: hidden;
padding: 0 12px;
position: relative;
text-align: center;
-webkit-transition: background-color .218s, border-color .218s, box-shadow .218s;
transition: background-color .218s, border-color .218s, box-shadow .218s;
vertical-align: middle;
white-space: nowrap;
width: auto;
width: 240px;
min-width: min-content;
}
.gsi-material-button .gsi-material-button-icon {
height: 20px;
margin-right: 12px;
min-width: 20px;
width: 20px;
}
.gsi-material-button .gsi-material-button-content-wrapper {
-webkit-align-items: center;
align-items: center;
display: flex;
-webkit-flex-direction: row;
flex-direction: row;
-webkit-flex-wrap: nowrap;
flex-wrap: nowrap;
height: 100%;
justify-content: space-between;
position: relative;
width: 100%;
}
.gsi-material-button .gsi-material-button-contents {
-webkit-flex-grow: 1;
flex-grow: 1;
font-family: 'Roboto', arial, sans-serif;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: top;
}
.gsi-material-button .gsi-material-button-state {
-webkit-transition: opacity .218s;
transition: opacity .218s;
bottom: 0;
left: 0;
opacity: 0;
position: absolute;
right: 0;
top: 0;
}
.gsi-material-button:disabled {
cursor: default;
background-color: #ffffff61;
border-color: #1f1f1f1f;
}
.gsi-material-button:disabled .gsi-material-button-contents {
opacity: 38%;
}
.gsi-material-button:disabled .gsi-material-button-icon {
opacity: 38%;
}
.gsi-material-button:not(:disabled):active .gsi-material-button-state,
.gsi-material-button:not(:disabled):focus .gsi-material-button-state {
background-color: #303030;
opacity: 12%;
}
.gsi-material-button:not(:disabled):hover .gsi-material-button-state {
background-color: #303030;
opacity: 8%;
}
</style>

@ -0,0 +1,127 @@
<template>
<div class="soc-wrapper">
<button class="gsi-material-button">
<div class="gsi-material-button-state"></div>
<div class="gsi-material-button-content-wrapper">
<div class="gsi-material-button-icon">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: block;">
<path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"></path>
<path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"></path>
<path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"></path>
<path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"></path>
<path fill="none" d="M0 0h48v48H0z"></path>
</svg>
</div>
<span class="gsi-material-button-contents">Sign in with Google</span>
<span style="display: none;">Sign in with Google</span>
</div>
</button>
</div>
</template>
<style scoped>
.soc-wrapper {
width: 100%;
}
.gsi-material-button {
display: block;
margin: 0px auto;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-webkit-appearance: none;
background-color: WHITE;
background-image: none;
border: 1px solid var(--grey-light);
-webkit-border-radius: 5px;
border-radius: 5px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: #1f1f1f;
cursor: pointer;
font-family: 'Roboto', arial, sans-serif;
font-size: 14px;
height: 46px;
letter-spacing: 0.25px;
outline: none;
overflow: hidden;
padding: 0 12px;
position: relative;
text-align: center;
-webkit-transition: background-color .218s, border-color .218s, box-shadow .218s;
transition: background-color .218s, border-color .218s, box-shadow .218s;
vertical-align: middle;
white-space: nowrap;
width: auto;
width: 240px;
min-width: min-content;
}
.gsi-material-button .gsi-material-button-icon {
height: 20px;
margin-right: 12px;
min-width: 20px;
width: 20px;
}
.gsi-material-button .gsi-material-button-content-wrapper {
-webkit-align-items: center;
align-items: center;
display: flex;
-webkit-flex-direction: row;
flex-direction: row;
-webkit-flex-wrap: nowrap;
flex-wrap: nowrap;
height: 100%;
justify-content: space-between;
position: relative;
width: 100%;
}
.gsi-material-button .gsi-material-button-contents {
-webkit-flex-grow: 1;
flex-grow: 1;
font-family: 'Roboto', arial, sans-serif;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: top;
}
.gsi-material-button .gsi-material-button-state {
-webkit-transition: opacity .218s;
transition: opacity .218s;
bottom: 0;
left: 0;
opacity: 0;
position: absolute;
right: 0;
top: 0;
}
.gsi-material-button:disabled {
cursor: default;
background-color: #ffffff61;
border-color: #1f1f1f1f;
}
.gsi-material-button:disabled .gsi-material-button-contents {
opacity: 38%;
}
.gsi-material-button:disabled .gsi-material-button-icon {
opacity: 38%;
}
.gsi-material-button:not(:disabled):active .gsi-material-button-state,
.gsi-material-button:not(:disabled):focus .gsi-material-button-state {
background-color: #303030;
opacity: 12%;
}
.gsi-material-button:not(:disabled):hover .gsi-material-button-state {
background-color: #303030;
opacity: 8%;
}
</style>

@ -0,0 +1,11 @@
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')

@ -0,0 +1,25 @@
import { createRouter, createWebHistory } from 'vue-router'
import LoginView from "../views/LoginView.vue"
import RegisterView from "../views/RegisterView.vue"
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
redirect: { path: '/register' },
},
{
path: '/register',
name: 'register',
component: RegisterView,
},
{
path: '/login',
name: 'login',
component: LoginView,
}
]
})
export default router

@ -0,0 +1,155 @@
<script setup lang="ts">
import GoogleLogin from '../components/GoogleLogin.vue'
import GitHubLogin from '../components/GitHubLogin.vue'
import { RouterLink } from 'vue-router'
</script>
<template>
<div class="wrapper">
<div class="container">
<img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="160"/>
<div class="login">
<div class="socials">
<GoogleLogin />
<GitHubLogin />
</div>
<p class="separat-or"><span>or</span></p>
<input type="email" name="tlg_email" id="tlg_email" placeholder="Email address">
<input type="password" name="tlg_password" id="tlg_password" placeholder="Password">
<button type="submit">Sign In</button>
<div class="remember">
<label for="tlg_remember" class="chk-container">Remember me for 30 days
<input type="checkbox" name="tlg_remember" id="tlg_remember">
<span class="checkmark"></span>
</label>
</div>
</div>
</div>
<div class="view-switch">Don't have an account? <RouterLink class="rlink" to="/register">Create an account.</RouterLink></div>
</div>
</template>
<style>
.view-switch {
text-align: center;
margin-top: 4px;
}
.rlink {
text-decoration: none;
color: var(--purple);
font-weight: 700;
}
.rlink:hover {
color: var(--purple-light);
}
.logo {
display: block;
margin: 1em auto 0em auto;
}
.container {
padding: 2em 4em;
background-color: var(--white-soft);
border-radius: 5px;
max-width: 440px;
filter: drop-shadow(3px 6px 6px var(--color-drop-shadow));
margin: auto;
margin-top: 6vh;
}
.login {
display: flex;
flex-direction: column;
}
.socials {
margin: 3em 0em;
}
.socials > * {
margin-bottom: 0.5em;
}
.separat-or {
background-color: var(--white-soft);
text-align: center;
margin: 0px auto;
margin-bottom: 3em;
width: 90%;
line-height: 0.1em;
border-bottom: 2px solid var(--grey-light);
}
.separat-or span {
background: var(--white-soft);
padding:0 10px;
}
.remember {
margin: 1em;
margin-bottom: 2em;
position: relative;
}
/* custom checkmark code from https://www.w3schools.com/howto/howto_css_custom_checkbox.asp */
/* Customize the label (the container) */
.chk-container {
display: block;
position: relative;
padding-left: 25px;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/* Hide the browser's default checkbox */
.chk-container input {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
}
/* Create a custom checkbox */
.checkmark {
position: absolute;
top: 2px;
left: 0;
height: 18px;
width: 18px;
border-radius: 3px;
background-color: #ddd;
}
/* On mouse-over, add a grey background color */
.chk-container:hover input ~ .checkmark {
background-color: #bbb;
}
/* When the checkbox is checked, add a blue background */
.chk-container input:checked ~ .checkmark {
background-color: var(--purple);
}
/* Create the checkmark/indicator (hidden when not checked) */
.checkmark:after {
content: "";
position: absolute;
display: none;
}
/* Show the checkmark when checked */
.chk-container input:checked ~ .checkmark:after {
display: block;
}
/* Style the checkmark/indicator */
.chk-container .checkmark:after {
left: 7px;
top: 3px;
width: 5px;
height: 10px;
border: solid white;
border-width: 0 2px 2px 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
</style>

@ -0,0 +1,156 @@
<script setup lang="ts">
import GoogleLogin from '../components/GoogleLogin.vue'
import GitHubLogin from '../components/GitHubLogin.vue'
import { RouterLink } from 'vue-router'
</script>
<template>
<div class="wrapper">
<div class="container">
<img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="160"/>
<div class="login">
<div class="socials">
<GoogleLogin />
<GitHubLogin />
</div>
<p class="separat-or"><span>or</span></p>
<input type="email" name="tlg_email" id="tlg_email" placeholder="Email address">
<input type="password" name="tlg_password" id="tlg_password" placeholder="Password">
<input type="password" name="tlg_password_conf" id="tlg_password_conf" placeholder="Confirm password">
<button type="submit">Sign In</button>
<div class="remember">
<label for="tlg_remember" class="chk-container">Remember me for 30 days
<input type="checkbox" name="tlg_remember" id="tlg_remember">
<span class="checkmark"></span>
</label>
</div>
</div>
</div>
<div class="view-switch">Already have an account? <RouterLink class="rlink" to="/login">Sign in.</RouterLink></div>
</div>
</template>
<style>
.view-switch {
text-align: center;
margin-top: 4px;
}
.rlink {
text-decoration: none;
color: var(--purple);
font-weight: 700;
}
.rlink:hover {
color: var(--purple-light);
}
.logo {
display: block;
margin: 1em auto 0em auto;
}
.container {
padding: 2em 4em;
background-color: var(--white-soft);
border-radius: 5px;
max-width: 440px;
filter: drop-shadow(3px 6px 6px var(--color-drop-shadow));
margin: auto;
margin-top: 6vh;
}
.login {
display: flex;
flex-direction: column;
}
.socials {
margin: 3em 0em;
}
.socials > * {
margin-bottom: 0.5em;
}
.separat-or {
background-color: var(--white-soft);
text-align: center;
margin: 0px auto;
margin-bottom: 3em;
width: 90%;
line-height: 0.1em;
border-bottom: 2px solid var(--grey-light);
}
.separat-or span {
background: var(--white-soft);
padding:0 10px;
}
.remember {
margin: 1em;
margin-bottom: 2em;
position: relative;
}
/* custom checkmark code from https://www.w3schools.com/howto/howto_css_custom_checkbox.asp */
/* Customize the label (the container) */
.chk-container {
display: block;
position: relative;
padding-left: 25px;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/* Hide the browser's default checkbox */
.chk-container input {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
}
/* Create a custom checkbox */
.checkmark {
position: absolute;
top: 2px;
left: 0;
height: 18px;
width: 18px;
border-radius: 3px;
background-color: #ddd;
}
/* On mouse-over, add a grey background color */
.chk-container:hover input ~ .checkmark {
background-color: #bbb;
}
/* When the checkbox is checked, add a blue background */
.chk-container input:checked ~ .checkmark {
background-color: var(--purple);
}
/* Create the checkmark/indicator (hidden when not checked) */
.checkmark:after {
content: "";
position: absolute;
display: none;
}
/* Show the checkmark when checked */
.chk-container input:checked ~ .checkmark:after {
display: block;
}
/* Style the checkmark/indicator */
.chk-container .checkmark:after {
left: 7px;
top: 3px;
width: 5px;
height: 10px;
border: solid white;
border-width: 0 2px 2px 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
</style>

@ -0,0 +1,15 @@
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<style>
@media (min-width: 1024px) {
.about {
min-height: 100vh;
display: flex;
align-items: center;
}
}
</style>

@ -0,0 +1,12 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"composite": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}

@ -0,0 +1,11 @@
{
"files": [],
"references": [
{
"path": "./tsconfig.node.json"
},
{
"path": "./tsconfig.app.json"
}
]
}

@ -0,0 +1,16 @@
{
"extends": "@tsconfig/node18/tsconfig.json",
"include": [
"vite.config.*",
"vitest.config.*",
"cypress.config.*",
"nightwatch.conf.*",
"playwright.config.*"
],
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
}
}

@ -0,0 +1,16 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
Loading…
Cancel
Save