profile menu
This commit is contained in:
80
ui/_/code/shared.css
Normal file
80
ui/_/code/shared.css
Normal file
@@ -0,0 +1,80 @@
|
||||
:root {
|
||||
--tan: #E6D7AA;
|
||||
--accent: black;
|
||||
--purple: #251D44;
|
||||
--green: #0B5538;
|
||||
--red: #BC1C02;
|
||||
--brown: #c6a476;
|
||||
--orange: #FE9201;
|
||||
--periwinkle: #655BAF;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--tan: #251D44;
|
||||
--accent: #AF7323;
|
||||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Canterbury';
|
||||
src: url('/_/fonts/Canterbury/Canterbury.ttf') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'BonaNova';
|
||||
src: url('/_/fonts/BonaNova/BonaNova-Regular.woff') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'BonaNova';
|
||||
src: url('/_/fonts/BonaNova/BonaNova-Bold.woff') format('truetype');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'BonaNova', sans-serif;
|
||||
font-size: 16px;
|
||||
background-color: var(--tan);
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
#title {
|
||||
padding: 5px 10px;
|
||||
font-size: 1.7rem;
|
||||
position: fixed; top: 4.5vh; left: 6vw;
|
||||
cursor: pointer; z-index: 1;
|
||||
}
|
||||
|
||||
a {
|
||||
cursor: default;
|
||||
text-decoration: none;
|
||||
text-underline-offset: 5px;
|
||||
transition: background .02s, color .2s;
|
||||
user-select: none;
|
||||
color: var(--accent);
|
||||
display: inline-block; /* makes background and padding behave */
|
||||
padding: 0.2em 0.5em; /* adds breathing room */
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
background: var(--green);
|
||||
color: var(--tan);
|
||||
}
|
||||
|
||||
a:active {
|
||||
background: var(--red); /* background color works now */
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: var(--green);
|
||||
color: var(--tan);
|
||||
padding: 1em;
|
||||
box-shadow: none;
|
||||
}
|
||||
@@ -31,6 +31,37 @@ window.html = function html(elementString) {
|
||||
return doc.body.firstChild;
|
||||
}
|
||||
|
||||
window.util = {}
|
||||
window.util.getColor = function(name) {
|
||||
const rootStyles = getComputedStyle(document.documentElement);
|
||||
const color = rootStyles.getPropertyValue(`--${name}`).trim();
|
||||
if(!color) {
|
||||
throw new Error("Color not found")
|
||||
}
|
||||
return color
|
||||
}
|
||||
|
||||
window.util.observeClassChange = (el, callback) => {
|
||||
if (!el || !(el instanceof Element)) {
|
||||
throw new Error("observeClassChange requires a valid DOM element.");
|
||||
}
|
||||
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
if (mutation.type === "attributes" && mutation.attributeName === "class") {
|
||||
callback(el.classList);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(el, {
|
||||
attributes: true,
|
||||
attributeFilter: ["class"]
|
||||
});
|
||||
|
||||
return observer; // Optional: return it so you can disconnect later
|
||||
}
|
||||
|
||||
|
||||
/* JQUERY */
|
||||
|
||||
|
||||
3
ui/_/icons/profile.svg
Normal file
3
ui/_/icons/profile.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="88" height="124" viewBox="0 0 88 124" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.998" d="M42.4512 2.00195C52.1659 2.22835 61.398 4.45649 70.166 8.69238L70.3818 8.79688L70.6162 8.84668C72.5686 9.26638 74.537 9.47923 76.5195 9.48535C76.5062 11.0178 76.3492 12.5388 76.0479 14.0508C74.4195 16.4705 72.6152 18.7571 70.6279 20.9072L69.8799 21.7168L70.1641 22.7812C71.785 28.8491 72.6458 35.0483 72.7471 41.3818L72.7549 41.8369L72.958 42.2432C74.3564 45.0408 75.7681 47.8651 77.1934 50.7148C76.401 51.7697 75.5014 52.7412 74.4893 53.6279L73.8906 54.1533L73.8164 54.9463C73.2326 61.1851 71.2275 66.786 67.8037 71.7871C66.3409 71.9333 64.8778 72.0802 63.415 72.2266C61.648 72.4034 59.8809 72.5803 58.1143 72.7568L56.9131 72.877L56.46 73.9951C55.1158 77.3095 54.9178 80.7587 55.8496 84.2715L55.9658 84.708L56.2578 85.0527C58.3856 87.5622 60.8538 89.6502 63.6553 91.3105L63.7783 91.3838L63.9102 91.4385C70.6068 94.2094 77.192 97.0352 83.665 99.9141C72.8406 106.409 62.2808 113.347 51.9873 120.731C49.5114 121.96 46.9641 122.264 44.2627 121.648C30.7653 112.891 16.9807 104.63 2.91113 96.8623C2.98649 96.7878 3.06425 96.7148 3.14453 96.6436C9.6346 94.2535 15.6931 91.0299 21.3154 86.9707L21.5225 86.8213L21.6855 86.625C23.5522 84.3704 24.9161 81.8385 25.7686 79.041L25.8184 78.877L25.8398 78.7061C26.5676 72.8871 26.5676 67.0651 25.8398 61.2461L25.7744 60.7236L25.4609 60.3018C16.1326 47.7366 13.0625 33.9256 16.21 18.7246C21.8795 8.29751 30.5529 2.76795 42.4512 2.00195Z" fill="#FE9201" fill-opacity="0.36" stroke="#FE9201" stroke-width="4"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -1,78 +0,0 @@
|
||||
:root {
|
||||
--tan: #E6D7AA;
|
||||
--accent: black;
|
||||
--purple: #251D44;
|
||||
--green: #0B5538;
|
||||
--red: #BC1C02;
|
||||
--brown: #c6a476;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--tan: #251D44;
|
||||
--accent: #AF7323;
|
||||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Canterbury';
|
||||
src: url('/_/fonts/Canterbury/Canterbury.ttf') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'BonaNova';
|
||||
src: url('/_/fonts/BonaNova/BonaNova-Regular.woff') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'BonaNova';
|
||||
src: url('/_/fonts/BonaNova/BonaNova-Bold.woff') format('truetype');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'BonaNova', sans-serif;
|
||||
font-size: 16px;
|
||||
background-color: var(--tan);
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
#title {
|
||||
padding: 5px 10px;
|
||||
font-size: 1.7rem;
|
||||
position: fixed; top: 4.5vh; left: 6vw;
|
||||
cursor: pointer; z-index: 1;
|
||||
}
|
||||
|
||||
a {
|
||||
cursor: default;
|
||||
text-decoration: none;
|
||||
text-underline-offset: 5px;
|
||||
transition: background .02s, color .2s;
|
||||
user-select: none;
|
||||
color: var(--accent);
|
||||
display: inline-block; /* makes background and padding behave */
|
||||
padding: 0.2em 0.5em; /* adds breathing room */
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
background: var(--green);
|
||||
color: var(--tan);
|
||||
}
|
||||
|
||||
a:active {
|
||||
background: var(--red); /* background color works now */
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: var(--green);
|
||||
color: var(--tan);
|
||||
padding: 1em;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<title>Hyperia</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" href="_/icons/logo.svg">
|
||||
<link rel="stylesheet" href="index.css">
|
||||
<link rel="stylesheet" href="_/code/shared.css">
|
||||
<style>
|
||||
|
||||
body {
|
||||
@@ -70,10 +70,10 @@
|
||||
|
||||
<h2 style="margin-left: 2.5vw; font-size: 2rem; font-family: Canterbury">5 Main Goals:</h2>
|
||||
|
||||
<ol style="font-size: 1.1rem; line-height: 1.3;">
|
||||
<ol style="line-height: 1.3;">
|
||||
<li style="margin-bottom: 3.5rem;">
|
||||
<strong>Reintroduce Heroism and Romance into Western Life</strong><br>
|
||||
When men are disconnected from ancestry, God, and land, we no longer have anything to fight for. Therefore, we will not fight.<br><br>
|
||||
<strong>Restore Romance and Heroism in Western Life</strong><br>
|
||||
When men are separated from ancestry, God, and land, men no longer have anything to fight for. Therefore, men will not fight.<br><br>
|
||||
When men do not fight, women are unprotected. They hate the men for being weak, and the men hate them too.<br><br>
|
||||
This is the cycle we are in, and this is the cycle we must break.<br><br>
|
||||
Hyperia Security allows men to be protectors of God and tradition. It allows them to fight for a society which is directly linked to our past and our future. We believe that, given this opportunity, men will rise to the occasion.<br><br>
|
||||
@@ -94,8 +94,8 @@
|
||||
</li>
|
||||
|
||||
<li style="margin-bottom: 3.5rem;">
|
||||
<strong>Revitalize Classical Christian Culture</strong><br>
|
||||
Currently, America is laden with exposure to secular and anti-Western influences. Hyperia will provide spaces, which are digital and eventually physical, that abide by Christian rules and are in favor of Western culture.
|
||||
<strong>Create a Network of Classical Christian Schools</strong><br>
|
||||
We want to connect these schools and provide resources to them.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<title>Hyperia</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" href="_/icons/logo.svg">
|
||||
<link rel="stylesheet" href="index.css">
|
||||
<link rel="stylesheet" href="_/code/shared.css">
|
||||
<style>
|
||||
#items {
|
||||
position: absolute;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<title>Hyperia</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" href="_/icons/logo.svg">
|
||||
<link rel="stylesheet" href="index.css">
|
||||
<link rel="stylesheet" href="_/code/shared.css">
|
||||
<style>
|
||||
#items {
|
||||
position: absolute;
|
||||
|
||||
65
ui/site/components/OptionsMenu.js
Normal file
65
ui/site/components/OptionsMenu.js
Normal file
@@ -0,0 +1,65 @@
|
||||
css(`
|
||||
options-menu {
|
||||
position: absolute;
|
||||
right: -.5em;
|
||||
top: -.3em;
|
||||
width: 0;
|
||||
height: 0;
|
||||
background-color: var(--orange);
|
||||
opacity: 30%;
|
||||
transition: width 0.2s, height 0.2s;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
options-menu * {
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
options-menu.closed * {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
options-menu.open {
|
||||
width: 10em;
|
||||
height: 15em;
|
||||
display: block;
|
||||
}
|
||||
|
||||
options-menu.open * {
|
||||
opacity: 100%;
|
||||
}
|
||||
`)
|
||||
|
||||
export default class OptionsMenu extends HTMLElement {
|
||||
|
||||
connectedCallback() {
|
||||
this.render()
|
||||
|
||||
util.observeClassChange(this, (cl) => {
|
||||
this.render()
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
if(this.classList.contains("open")) {
|
||||
setTimeout(() => {
|
||||
this.innerHTML = /* html */`
|
||||
<a href="signout" style="position: absolute; left: 0px; color: white; z-index: 2">sign out</a>
|
||||
`
|
||||
}, 200)
|
||||
} else {
|
||||
this.innerHTML === ""
|
||||
}
|
||||
}
|
||||
|
||||
logout() {
|
||||
fetch('/signout', { method: 'GET', credentials: 'include' })
|
||||
.then(() => {
|
||||
// Force a clean full-page reload of "/"
|
||||
window.location.replace('/?loggedout');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("options-menu", OptionsMenu)
|
||||
50
ui/site/components/ProfileButton.js
Normal file
50
ui/site/components/ProfileButton.js
Normal file
@@ -0,0 +1,50 @@
|
||||
import OptionsMenu from "./OptionsMenu.js"
|
||||
|
||||
css(`
|
||||
profile-button {
|
||||
display: block;
|
||||
width: 1.5em
|
||||
}
|
||||
`)
|
||||
|
||||
export default class ProfileButton extends HTMLElement {
|
||||
hovered = false
|
||||
|
||||
connectedCallback() {
|
||||
this.render()
|
||||
|
||||
document.addEventListener("mousemove", (e) => {
|
||||
this.previousHovered = this.hovered
|
||||
if(e.target.closest("profile-button")) {
|
||||
this.hovered = true
|
||||
} else {
|
||||
this.hovered = false
|
||||
}
|
||||
if(this.hovered !== this.previousHovered) {
|
||||
if(this.hovered === true) {
|
||||
this.render()
|
||||
setTimeout(() => {
|
||||
this.querySelector("options-menu").className = "open"
|
||||
})
|
||||
} else {
|
||||
this.querySelector("options-menu").className = "closed"
|
||||
setTimeout(() => {
|
||||
this.render()
|
||||
}, 140)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
this.innerHTML = /* html */`
|
||||
<svg style="position: absolute;" viewBox="0 0 88 124" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.998" d="M42.4512 2.00195C52.1659 2.22835 61.398 4.45649 70.166 8.69238L70.3818 8.79688L70.6162 8.84668C72.5686 9.26638 74.537 9.47923 76.5195 9.48535C76.5062 11.0178 76.3492 12.5388 76.0479 14.0508C74.4195 16.4705 72.6152 18.7571 70.6279 20.9072L69.8799 21.7168L70.1641 22.7812C71.785 28.8491 72.6458 35.0483 72.7471 41.3818L72.7549 41.8369L72.958 42.2432C74.3564 45.0408 75.7681 47.8651 77.1934 50.7148C76.401 51.7697 75.5014 52.7412 74.4893 53.6279L73.8906 54.1533L73.8164 54.9463C73.2326 61.1851 71.2275 66.786 67.8037 71.7871C66.3409 71.9333 64.8778 72.0802 63.415 72.2266C61.648 72.4034 59.8809 72.5803 58.1143 72.7568L56.9131 72.877L56.46 73.9951C55.1158 77.3095 54.9178 80.7587 55.8496 84.2715L55.9658 84.708L56.2578 85.0527C58.3856 87.5622 60.8538 89.6502 63.6553 91.3105L63.7783 91.3838L63.9102 91.4385C70.6068 94.2094 77.192 97.0352 83.665 99.9141C72.8406 106.409 62.2808 113.347 51.9873 120.731C49.5114 121.96 46.9641 122.264 44.2627 121.648C30.7653 112.891 16.9807 104.63 2.91113 96.8623C2.98649 96.7878 3.06425 96.7148 3.14453 96.6436C9.6346 94.2535 15.6931 91.0299 21.3154 86.9707L21.5225 86.8213L21.6855 86.625C23.5522 84.3704 24.9161 81.8385 25.7686 79.041L25.8184 78.877L25.8398 78.7061C26.5676 72.8871 26.5676 67.0651 25.8398 61.2461L25.7744 60.7236L25.4609 60.3018C16.1326 47.7366 13.0625 33.9256 16.21 18.7246C21.8795 8.29751 30.5529 2.76795 42.4512 2.00195Z"
|
||||
fill="${this.hovered ? util.getColor("orange") : util.getColor("periwinkle")}" fill-opacity="0.36" stroke="${this.hovered ? util.getColor("orange") : util.getColor("periwinkle")}" stroke-width="4"/>
|
||||
</svg>
|
||||
<options-menu class="closed"></options-menu>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("profile-button", ProfileButton)
|
||||
0
ui/site/index.css
Normal file
0
ui/site/index.css
Normal file
@@ -4,23 +4,14 @@
|
||||
<title>Hyperia</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" href="_/icons/logo.svg">
|
||||
<link rel="stylesheet" href="index.css">
|
||||
<link rel="stylesheet" href="_/code/shared.css">
|
||||
<script src="_/code/util.js"></script>
|
||||
<script type="module">
|
||||
import ProfileButton from "./components/ProfileButton.js"
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<span id="title" class="link" onclick='window.location.href="/"'>hyperia
|
||||
</span>
|
||||
<img class="main-image">
|
||||
<div class="links" style="z-index: 1; cursor: default; position: fixed; top: 5.5vh; right: 4.5vw">
|
||||
<a href="#" onclick="logout(); return false;">sign out</a>
|
||||
<script>
|
||||
function logout() {
|
||||
fetch('/signout', { method: 'GET', credentials: 'include' })
|
||||
.then(() => {
|
||||
// Force a clean full-page reload of "/"
|
||||
window.location.replace('/?loggedout');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
<span id="title" class="link" onclick='window.location.href="/"'>hyperia</span>
|
||||
<profile-button style="z-index: 1; cursor: default; position: fixed; top: 5.5vh; right: 4.5vw"></profile-button>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user