feat: mobile nav with animations

This commit is contained in:
Alexander Daichendt 2025-01-03 19:50:29 +01:00
parent a839560bff
commit 3bf65ae7ab
4 changed files with 97 additions and 23 deletions

View file

@ -1,15 +0,0 @@
---
import HeaderLink from "./HeaderLink.astro";
---
<header class="mb-8 w-full lg:w-[768px] max-w-[calc(100%-2em)] lg:mx-auto">
<nav>
<div class="flex gap-4">
<HeaderLink href="/">Home</HeaderLink>
<HeaderLink href="/blog">Blog</HeaderLink>
<HeaderLink href="/projects">Projects</HeaderLink>
<HeaderLink href="/publications">Publications</HeaderLink>
<HeaderLink href="/contact">Contact</HeaderLink>
</div>
</nav>
</header>

View file

@ -0,0 +1,78 @@
---
import { Icon } from "astro-icon/components";
import HeaderLink from "./HeaderLink.astro";
---
<header
class="mb-8 w-full lg:w-[768px] max-w-[calc(100%-2em)] lg:mx-auto overflow-scroll hidden lg:block"
>
<nav>
<div class="flex gap-4">
<HeaderLink href="/">Home</HeaderLink>
<HeaderLink href="/blog">Blog</HeaderLink>
<HeaderLink href="/projects">Projects</HeaderLink>
<HeaderLink href="/publications">Publications</HeaderLink>
<HeaderLink href="/contact">Contact</HeaderLink>
</div>
</nav>
</header>
<button id="menu" class="lg:hidden relative w-[30px] h-[30px]">
<Icon
name="mdi:menu"
id="iconMenu"
class="absolute inset-0 transition-all duration-300 ease-in-out"
size={30}
/>
<Icon
name="mdi:close"
id="iconClose"
class="absolute inset-0 opacity-0 rotate-90 transition-all duration-300 ease-in-out"
size={30}
/>
</button>
<header
id="drawer"
class="fixed top-16 right-0 h-full bg-neutral-50 shadow dark:bg-gray-700 p-6 rounded w-54 transform translate-x-full transition-transform duration-300 ease-in-out"
>
<div class="flex flex-col gap-4">
<HeaderLink href="/">Home</HeaderLink>
<HeaderLink href="/blog">Blog</HeaderLink>
<HeaderLink href="/projects">Projects</HeaderLink>
<HeaderLink href="/publications">Publications</HeaderLink>
<HeaderLink href="/contact">Contact</HeaderLink>
</div>
</header>
<script>
const menu = document.getElementById("menu");
const drawer = document.getElementById("drawer");
function toggle() {
drawer.classList.toggle("translate-x-full");
document.body.classList.toggle("overflow-hidden");
if (iconMenu.classList.contains("opacity-0")) {
iconMenu.classList.remove("opacity-0", "rotate-90");
iconClose.classList.add("opacity-0", "rotate-90");
} else {
iconMenu.classList.add("opacity-0", "rotate-90");
iconClose.classList.remove("opacity-0", "rotate-90");
}
}
menu.addEventListener("click", () => {
toggle();
});
// click-away listener
document.addEventListener("click", (event) => {
console.log("click outside");
if (
!drawer.classList.contains("hidden") &&
!drawer.contains(event.target) &&
!menu.contains(event.target)
) {
toggle();
}
});
</script>