apply prettier formatting
Some checks failed
renovate / renovate (push) Has been cancelled

This commit is contained in:
2025-06-08 16:45:36 -05:00
parent 67f12ecf72
commit 51041f6ae9
32 changed files with 3303 additions and 2509 deletions

View File

@@ -1,10 +1,10 @@
---
import ThemeToggle from './ThemeToggle.astro';
import directus from "../../lib/directus"
import { readSingleton } from "@directus/sdk";
import directus from '../../lib/directus';
import { readSingleton } from '@directus/sdk';
const global = await directus.request(readSingleton("global"));
const global = await directus.request(readSingleton('global'));
const navItems = [
{ text: 'Home', href: '/' },
@@ -15,68 +15,102 @@ const navItems = [
];
const pathname = new URL(Astro.request.url).pathname;
const currentPath = pathname.slice(1); // remove the first "/"
const currentPath = pathname.slice(1);
---
<header class="py-4 fixed top-0 left-0 right-0 z-40 bg-white dark:bg-zinc-900 border-b border-zinc-100 dark:border-zinc-800">
<div class="max-w-3xl mx-auto px-4 flex items-center justify-between">
<header
class="fixed left-0 right-0 top-0 z-40 border-b border-zinc-100 bg-white py-4 dark:border-zinc-800 dark:bg-zinc-900"
>
<div class="mx-auto flex max-w-3xl items-center justify-between px-4">
<!-- Logo -->
<a href="/" class="font-bold text-xl text-zinc-900 dark:text-white">{global.initals}</a>
<a href="/" class="text-xl font-bold text-zinc-900 dark:text-white">{global.initals}</a>
<!-- Desktop navigation -->
<nav class="hidden sm:flex items-center space-x-6">
{navItems.map(item => {
const isActive = currentPath === (item.href === '/' ? '' : item.href.slice(1));
return (
<a
href={item.href}
class={`text-sm font-medium ${isActive
? 'text-zinc-900 dark:text-white'
: 'text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white'}`}
>
{item.text}
</a>
)
})}
<nav class="hidden items-center space-x-6 sm:flex">
{
navItems.map((item) => {
const isActive = currentPath === (item.href === '/' ? '' : item.href.slice(1));
return (
<a
href={item.href}
class={`text-sm font-medium ${
isActive
? 'text-zinc-900 dark:text-white'
: 'text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white'
}`}
>
{item.text}
</a>
);
})
}
<ThemeToggle />
</nav>
<!-- Mobile menu button -->
<button id="mobile-menu-button" class="sm:hidden flex items-center" aria-label="Menu">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 text-zinc-900 dark:text-white">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
<button id="mobile-menu-button" class="flex items-center sm:hidden" aria-label="Menu">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="h-6 w-6 text-zinc-900 dark:text-white"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"></path>
</svg>
</button>
</div>
</header>
<!-- Mobile menu overlay -->
<div id="mobile-menu" class="fixed inset-0 z-50 bg-white dark:bg-zinc-900 flex flex-col opacity-0 pointer-events-none transition-all duration-300 ease-in-out">
<div class="flex justify-between items-center p-4 border-b border-zinc-100 dark:border-zinc-800">
<a href="/" class="font-bold text-xl text-zinc-900 dark:text-white">JD</a>
<button id="close-menu-button" class="text-zinc-900 dark:text-white p-2 rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors" aria-label="Close menu">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
<div
id="mobile-menu"
class="pointer-events-none fixed inset-0 z-50 flex flex-col bg-white opacity-0 transition-all duration-300 ease-in-out dark:bg-zinc-900"
>
<div class="flex items-center justify-between border-b border-zinc-100 p-4 dark:border-zinc-800">
<a href="/" class="text-xl font-bold text-zinc-900 dark:text-white">JD</a>
<button
id="close-menu-button"
class="rounded-md p-2 text-zinc-900 transition-colors hover:bg-zinc-100 dark:text-white dark:hover:bg-zinc-800"
aria-label="Close menu"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="h-6 w-6"
>
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<nav class="flex-1 flex flex-col items-center justify-center space-y-6 text-center">
{navItems.map((item, index) => {
const isActive = currentPath === (item.href === '/' ? '' : item.href.slice(1));
return (
<a
href={item.href}
class={`text-lg font-medium mobile-nav-item opacity-0 translate-y-4 ${isActive
? 'text-zinc-900 dark:text-white'
: 'text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white'}`}
style={`transition-delay: ${index * 0.05}s;`}
>
{item.text}
</a>
)
})}
<div class="pt-4 mobile-nav-item opacity-0 translate-y-4" style="transition-delay: 0.25s;">
<nav class="flex flex-1 flex-col items-center justify-center space-y-6 text-center">
{
navItems.map((item, index) => {
const isActive = currentPath === (item.href === '/' ? '' : item.href.slice(1));
return (
<a
href={item.href}
class={`mobile-nav-item translate-y-4 text-lg font-medium opacity-0 ${
isActive
? 'text-zinc-900 dark:text-white'
: 'text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white'
}`}
style={`transition-delay: ${index * 0.05}s;`}
>
{item.text}
</a>
);
})
}
<div class="mobile-nav-item translate-y-4 pt-4 opacity-0" style="transition-delay: 0.25s;">
<ThemeToggle />
</div>
</nav>
@@ -92,44 +126,44 @@ const currentPath = pathname.slice(1); // remove the first "/"
const closeMenuButton = document.getElementById('close-menu-button');
const mobileMenu = document.getElementById('mobile-menu');
const navItems = document.querySelectorAll('.mobile-nav-item');
// Open menu with animations
mobileMenuButton?.addEventListener('click', () => {
if (!mobileMenu) return;
// Prevent body scrolling
document.body.style.overflow = 'hidden';
// Show menu with fade in
mobileMenu.classList.remove('pointer-events-none');
mobileMenu.classList.add('pointer-events-auto');
// Animate opacity
setTimeout(() => {
mobileMenu.style.opacity = '1';
// Animate each nav item with staggered delay
navItems.forEach(item => {
navItems.forEach((item) => {
setTimeout(() => {
item.classList.remove('opacity-0', 'translate-y-4');
}, 150);
});
}, 50);
});
// Close menu with animations
const closeMenu = () => {
if (!mobileMenu) return;
// Fade out nav items first
navItems.forEach(item => {
navItems.forEach((item) => {
item.classList.add('opacity-0', 'translate-y-4');
});
// Then fade out the menu
setTimeout(() => {
mobileMenu.style.opacity = '0';
// After animation completes, hide menu and restore scrolling
setTimeout(() => {
mobileMenu.classList.remove('pointer-events-auto');
@@ -138,39 +172,39 @@ const currentPath = pathname.slice(1); // remove the first "/"
}, 300);
}, 100);
};
// Close button event
closeMenuButton?.addEventListener('click', closeMenu);
// Close menu when clicking a link
const mobileLinks = mobileMenu?.querySelectorAll('a');
mobileLinks?.forEach(link => {
mobileLinks?.forEach((link) => {
link.addEventListener('click', closeMenu);
});
// Close menu on escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && mobileMenu?.classList.contains('pointer-events-auto')) {
closeMenu();
}
});
// Add smooth animation to header on scroll
const header = document.querySelector('header');
let lastScrollY = window.scrollY;
window.addEventListener('scroll', () => {
if (!header) return;
const currentScrollY = window.scrollY;
// Add shadow on scroll
if (currentScrollY > 10) {
header.classList.add('shadow-sm');
} else {
header.classList.remove('shadow-sm');
}
// Update last scroll position
lastScrollY = currentScrollY;
});
@@ -180,23 +214,29 @@ const currentPath = pathname.slice(1); // remove the first "/"
<style>
/* Smooth animations for mobile navigation */
.mobile-nav-item {
transition: opacity 0.5s ease, transform 0.5s ease, color 0.3s ease;
transition:
opacity 0.5s ease,
transform 0.5s ease,
color 0.3s ease;
}
/* Header transition */
header {
transition: box-shadow 0.3s ease, transform 0.3s ease, background-color 0.3s ease;
transition:
box-shadow 0.3s ease,
transform 0.3s ease,
background-color 0.3s ease;
}
/* Mobile menu button hover effect */
#mobile-menu-button {
transition: transform 0.2s ease;
}
#mobile-menu-button:hover {
transform: scale(1.05);
}
/* Mobile menu transition */
#mobile-menu {
transition: opacity 0.3s ease;