Added animations
All checks were successful
Deploy / deploy (push) Successful in 20s

This commit is contained in:
elijah 2024-11-04 12:11:42 +01:00
parent 5e43f076c3
commit d6960d0980
3 changed files with 193 additions and 34 deletions

View File

@ -3,13 +3,13 @@
--border-color: #2a5a5a; --border-color: #2a5a5a;
--text-muted: #88aaaa; --text-muted: #88aaaa;
--text-bright: #cef0f0; --text-bright: #cef0f0;
--glow-color: rgba(42, 90, 90, 0.4); --glow-color: rgba(42, 90, 90, 0.6);
} }
@keyframes pulse { @keyframes pulse {
0% { 0% {
box-shadow: 0 0 5px var(--glow-color); box-shadow: 0 0 5px var(--glow-color);
opacity: 0.7; opacity: 0.5;
} }
50% { 50% {
box-shadow: 0 0 10px var(--glow-color); box-shadow: 0 0 10px var(--glow-color);
@ -17,7 +17,7 @@
} }
100% { 100% {
box-shadow: 0 0 5px var(--glow-color); box-shadow: 0 0 5px var(--glow-color);
opacity: 0.7; opacity: 0.5;
} }
} }
@ -482,16 +482,21 @@ body::before {
} }
.contact-link { .contact-link {
display: flex;
align-items: center;
color: var(--text-bright);
text-decoration: none;
padding: 15px;
border: 1px solid var(--border-color); border: 1px solid var(--border-color);
padding: 15px;
margin: 15px 0;
cursor: pointer;
transition: transition:
border-color 0.3s ease, border-color 0.3s ease,
background-color 0.3s ease; background-color 0.3s ease,
background: rgba(42, 90, 90, 0.05); box-shadow 0.3s ease,
transform 0.3s ease;
position: relative;
background: linear-gradient(
135deg,
rgba(42, 90, 90, 0.1),
rgba(42, 90, 90, 0.2)
);
clip-path: polygon( clip-path: polygon(
0 0, 0 0,
98% 0, 98% 0,
@ -500,11 +505,28 @@ body::before {
2% 100%, 2% 100%,
0 calc(100% - 15px) 0 calc(100% - 15px)
); );
transform: translateZ(20px);
box-shadow:
0 5px 15px rgba(0, 0, 0, 0.4),
0 10px 20px rgba(42, 90, 90, 0.3),
inset 0 1px rgba(255, 255, 255, 0.2),
inset -2px -2px 4px rgba(0, 0, 0, 0.5);
transform-style: preserve-3d;
perspective: 1000px;
backdrop-filter: blur(5px);
border-left: 3px solid rgba(42, 90, 90, 0.6);
border-top: 2px solid rgba(255, 255, 255, 0.15);
} }
.contact-link:hover { .contact-link:hover {
border-color: var(--text-bright); border-color: var(--text-bright);
background: rgba(42, 90, 90, 0.1); background: rgba(42, 90, 90, 0.1);
box-shadow:
0 5px 15px rgba(0, 0, 0, 0.3),
0 10px 20px rgba(42, 90, 90, 0.2),
inset 0 1px rgba(255, 255, 255, 0.2);
transform: translateY(-2px) translateZ(10px);
animation: pulse 2s infinite;
} }
.contact-icon { .contact-icon {

View File

@ -2,24 +2,60 @@
// atleast i'm not a reactfag. // atleast i'm not a reactfag.
// we add some fancy text typing animation blah blah blah // we add some fancy text typing animation blah blah blah
function writeoutnavlabel() { // it is quite overcomplicated. i have no hobbies
const firstNavIcon = document.querySelector('.nav-icon[href="#about"]'); function writeoutnavlabel(label) {
const label = firstNavIcon.querySelector(".nav-label"); if (label.getAttribute("data-animating") === "true") return;
const text = label.textContent;
const text = label.getAttribute("data-text") || label.textContent;
label.setAttribute("data-text", text);
label.textContent = ""; label.textContent = "";
label.style.opacity = "1"; label.style.opacity = "1";
label.setAttribute("data-animating", "true");
let i = 0; let i = 0;
function type() { let animationInterval = setInterval(() => {
if (i < text.length) { if (i < text.length) {
label.textContent += text.charAt(i); label.textContent += text.charAt(i);
i++; i++;
setTimeout(type, 180); } else {
clearInterval(animationInterval);
label.setAttribute("data-animating", "false");
const icon = label.closest(".nav-icon");
if (icon) {
icon.isAnimating = false;
icon.hoverAnimationDone = true;
}
}
}, 180);
label.setAttribute("data-animation-interval", animationInterval);
}
function eraselabel(label) {
if (label.getAttribute("data-animating") === "true") {
// clear the existing interval
const existingInterval = label.getAttribute("data-animation-interval");
if (existingInterval) {
clearInterval(existingInterval);
} }
} }
// why am i using a function inside a function?
// i don't know. i'm sorry. label.setAttribute("data-animating", "true");
type();
let eraseInterval = setInterval(() => {
const currentText = label.textContent;
if (currentText.length > 0) {
label.textContent = currentText.slice(0, -1);
} else {
clearInterval(eraseInterval);
label.setAttribute("data-animating", "false");
label.style.opacity = "0";
}
}, 100);
// store the interval so we can clear it if needed
// this is a terrible way to do this like horrible
label.setAttribute("data-animation-interval", eraseInterval);
} }
function updateTime() { function updateTime() {
@ -88,7 +124,7 @@ function getStatusClass(service) {
if (service.latency > 500000) return "status-warning"; if (service.latency > 500000) return "status-warning";
return "status-online"; return "status-online";
} }
// not sure if this is the best way to do this
function getGroupName(groupId) { function getGroupName(groupId) {
const groupNames = { const groupNames = {
4: "INFRASTRUCTURE", 4: "INFRASTRUCTURE",
@ -98,8 +134,8 @@ function getGroupName(groupId) {
return groupNames[groupId] || `GROUP ${groupId}`; return groupNames[groupId] || `GROUP ${groupId}`;
} }
// populate status page first
function createStatusHTML(services) { function createStatusHTML(services) {
// Group services by group_id
const groups = services.reduce((acc, service) => { const groups = services.reduce((acc, service) => {
const groupId = service.group_id; const groupId = service.group_id;
if (!acc[groupId]) acc[groupId] = []; if (!acc[groupId]) acc[groupId] = [];
@ -136,6 +172,7 @@ function createStatusHTML(services) {
.join(""); .join("");
} }
// status page func
function updateStatus() { function updateStatus() {
const statusContainer = document.getElementById("status-container"); const statusContainer = document.getElementById("status-container");
const averageUptimeElement = document.getElementById("average-uptime"); const averageUptimeElement = document.getElementById("average-uptime");
@ -201,16 +238,88 @@ window.addEventListener("scroll", () => {
}); });
document.querySelectorAll(".nav-icon").forEach((icon) => { document.querySelectorAll(".nav-icon").forEach((icon) => {
icon.classList.remove("active"); const label = icon.querySelector(".nav-label");
if (icon.getAttribute("href") === `#${current}`) { const isCurrentSection = icon.getAttribute("href") === `#${current}`;
icon.classList.add("active"); const wasActive = icon.classList.contains("active");
if (isCurrentSection) {
if (!wasActive) {
icon.classList.add("active");
// complete instantly
if (icon.isAnimating) {
const text = label.getAttribute("data-text") || label.textContent;
label.textContent = text;
label.setAttribute("data-animating", "false");
clearInterval(
parseInt(label.getAttribute("data-animation-interval")),
);
}
// only start if not currently animating
if (!icon.hoverAnimationDone) {
writeoutnavlabel(label);
}
icon.hoverAnimationDone = true;
}
} else {
if (wasActive) {
eraselabel(label);
icon.classList.remove("active");
icon.hoverAnimationDone = false;
icon.isAnimating = false;
}
} }
}); });
}); });
// dom content event listener document.querySelectorAll(".nav-icon").forEach((icon) => {
icon.hoverAnimationDone = false;
icon.isAnimating = false;
icon.addEventListener("mouseenter", () => {
if (!icon.classList.contains("active") && !icon.isAnimating) {
const label = icon.querySelector(".nav-label");
writeoutnavlabel(label);
icon.isAnimating = true;
}
});
icon.addEventListener("mouseleave", () => {
if (!icon.classList.contains("active")) {
const label = icon.querySelector(".nav-label");
eraselabel(label);
icon.isAnimating = false;
icon.hoverAnimationDone = false;
}
});
icon.addEventListener("click", (e) => {
const label = icon.querySelector(".nav-label");
// continue if already active
// prevent mouseleave from erasing label
if (icon.isAnimating) {
icon.hoverAnimationDone = true;
}
// if no animation, start one
else if (!icon.hoverAnimationDone) {
writeoutnavlabel(label);
icon.isAnimating = true;
icon.hoverAnimationDone = true;
}
label.style.opacity = "1";
});
});
// dom (196 reference) content event listener
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
writeoutnavlabel(); // write out active nav icon label instantly
const activeNavIcon = document.querySelector(".nav-icon.active");
if (activeNavIcon) {
const label = activeNavIcon.querySelector(".nav-label");
if (label) writeoutnavlabel(label);
}
// fancy console log
console.log( console.log(
"%cELIA.NETWORK", "%cELIA.NETWORK",
"color: #2a5a5a; font-size: 24px; font-weight: bold; text-shadow: 2px 2px 4px rgba(42, 90, 90, 0.4), 4px 4px 8px rgba(42, 90, 90, 0.2), 6px 6px 12px rgba(42, 90, 90, 0.1), 0 0 20px rgba(42, 90, 90, 0.3); transform: perspective(1000px) rotateX(20deg) rotateY(-10deg) translateZ(50px); animation: console3d 8s infinite cubic-bezier(0.4, 0, 0.2, 1), glow 2s infinite alternate; @keyframes console3d { 0% { transform: perspective(1000px) rotateX(20deg) rotateY(-10deg) translateZ(50px); } 25% { transform: perspective(1000px) rotateX(-15deg) rotateY(15deg) translateZ(75px); } 50% { transform: perspective(1000px) rotateX(10deg) rotateY(20deg) translateZ(100px); } 75% { transform: perspective(1000px) rotateX(-20deg) rotateY(-15deg) translateZ(75px); } 100% { transform: perspective(1000px) rotateX(20deg) rotateY(-10deg) translateZ(50px); } } @keyframes glow { from { text-shadow: 0 0 20px rgba(42, 90, 90, 0.3), 0 0 40px rgba(42, 90, 90, 0.2); } to { text-shadow: 0 0 40px rgba(42, 90, 90, 0.5), 0 0 80px rgba(42, 90, 90, 0.3); } }", "color: #2a5a5a; font-size: 24px; font-weight: bold; text-shadow: 2px 2px 4px rgba(42, 90, 90, 0.4), 4px 4px 8px rgba(42, 90, 90, 0.2), 6px 6px 12px rgba(42, 90, 90, 0.1), 0 0 20px rgba(42, 90, 90, 0.3); transform: perspective(1000px) rotateX(20deg) rotateY(-10deg) translateZ(50px); animation: console3d 8s infinite cubic-bezier(0.4, 0, 0.2, 1), glow 2s infinite alternate; @keyframes console3d { 0% { transform: perspective(1000px) rotateX(20deg) rotateY(-10deg) translateZ(50px); } 25% { transform: perspective(1000px) rotateX(-15deg) rotateY(15deg) translateZ(75px); } 50% { transform: perspective(1000px) rotateX(10deg) rotateY(20deg) translateZ(100px); } 75% { transform: perspective(1000px) rotateX(-20deg) rotateY(-15deg) translateZ(75px); } 100% { transform: perspective(1000px) rotateX(20deg) rotateY(-10deg) translateZ(50px); } } @keyframes glow { from { text-shadow: 0 0 20px rgba(42, 90, 90, 0.3), 0 0 40px rgba(42, 90, 90, 0.2); } to { text-shadow: 0 0 40px rgba(42, 90, 90, 0.5), 0 0 80px rgba(42, 90, 90, 0.3); } }",

View File

@ -203,14 +203,42 @@
<section id="contact" class="section"> <section id="contact" class="section">
<div class="section-title">CONTACT</div> <div class="section-title">CONTACT</div>
<div class="contact-links"> <div class="contact-links">
<a href="mailto:noc@elia.network" class="contact-link"> <div class="project-item">
<span class="contact-icon"></span> <div class="project-header">
NOC EMAIL <div class="entry">E-Mail</div>
</a> <span class="expand-icon">+</span>
<a href="https://t.me/beslikmeister" class="contact-link"> </div>
<span class="contact-icon"></span> <div class="project-content">
TELEGRAM <div class="project-links">
</a> <a
href="mailto:alerts@elia.network"
class="project-link"
>⎔ ALERTS →</a
>
<a
href="mailto:noc@elia.network"
class="project-link"
>⎔ NOC →</a
>
</div>
</div>
</div>
<div class="project-item">
<div class="project-header">
<div class="entry">TELEGRAM</div>
<span class="expand-icon">+</span>
</div>
<div class="project-content">
<div class="project-links">
<a
href="https://t.me/beslikmeister"
class="project-link"
>⎔ T.ME →</a
>
</div>
</div>
</div>
</div> </div>
</section> </section>
</div> </div>