mirror of
https://github.com/Floriansylvain/compact-portfolio.git
synced 2026-08-19 11:43:19 +02:00
feat: initialize server with essential files and configurations
- Added package.json and package-lock.json for project dependencies and metadata. - Created server.js to handle HTTP requests, serve files, and implement security headers. - Implemented minification functions for HTML, CSS, and JavaScript to optimize performance. - Added style.css for styling the application with a responsive design. - Introduced script.js for handling navigation and reveal animations. - Removed unused profile.webp image.
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
const prefersReduced =
|
||||
window.matchMedia &&
|
||||
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||||
|
||||
const revealables = document.querySelectorAll(".reveal");
|
||||
if (prefersReduced) {
|
||||
revealables.forEach((el) => el.classList.add("revealed"));
|
||||
} else {
|
||||
const io = new IntersectionObserver(
|
||||
(entries) => {
|
||||
for (const e of entries)
|
||||
if (e.isIntersecting) {
|
||||
e.target.classList.add("revealed");
|
||||
io.unobserve(e.target);
|
||||
}
|
||||
},
|
||||
{ threshold: 0.08, rootMargin: "0px 0px -10% 0px" }
|
||||
);
|
||||
revealables.forEach((el) => io.observe(el));
|
||||
}
|
||||
|
||||
const navLinks = [...document.querySelectorAll(".site-nav a")];
|
||||
const sections = navLinks
|
||||
.map((a) => document.querySelector(a.getAttribute("href")))
|
||||
.filter(Boolean);
|
||||
|
||||
let currentSection = null;
|
||||
|
||||
const spy = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((e) => {
|
||||
if (e.isIntersecting) {
|
||||
const id = "#" + e.target.id;
|
||||
|
||||
navLinks.forEach((a) => a.removeAttribute("aria-current"));
|
||||
const active = navLinks.find(
|
||||
(a) => a.getAttribute("href") === id
|
||||
);
|
||||
if (active) active.setAttribute("aria-current", "page");
|
||||
|
||||
if (currentSection !== id) {
|
||||
currentSection = id;
|
||||
history.replaceState(null, null, id);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
{ rootMargin: "-40% 0% -50% 0%", threshold: 0.01 }
|
||||
);
|
||||
sections.forEach((s) => s && spy.observe(s));
|
||||
|
||||
const menuBtn = document.getElementById("menuToggle");
|
||||
const nav = document.getElementById("primaryNav");
|
||||
if (menuBtn && nav) {
|
||||
const closeMenu = () => {
|
||||
nav.classList.remove("is-open");
|
||||
menuBtn.setAttribute("aria-expanded", "false");
|
||||
};
|
||||
const openMenu = () => {
|
||||
nav.classList.add("is-open");
|
||||
menuBtn.setAttribute("aria-expanded", "true");
|
||||
};
|
||||
const toggleMenu = () => {
|
||||
nav.classList.contains("is-open") ? closeMenu() : openMenu();
|
||||
};
|
||||
menuBtn.addEventListener("click", toggleMenu);
|
||||
nav.addEventListener("click", (e) => {
|
||||
const t = e.target;
|
||||
if (t && t.matches("a")) closeMenu();
|
||||
});
|
||||
document.addEventListener("click", (e) => {
|
||||
if (!nav.contains(e.target) && !menuBtn.contains(e.target)) closeMenu();
|
||||
});
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Escape") closeMenu();
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user