Files
siteloft/src/components/Header.astro
Ubuntu 9cfd926e9c Initial commit: SiteLoft.nl website
Full-service digital agency website built with Astro 5, Tailwind CSS v4,
and TypeScript. Includes 10 pages: homepage, diensten (development, hosting,
growth), pakketten, over ons, blog met eerste GEO-artikel, en contact.

Features: dark theme design system, glassmorphism UI, structured data/schema
markup voor SEO en GEO, content collections voor blog, responsive design,
sitemap generation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:11:56 +00:00

138 lines
4.9 KiB
Plaintext

---
const currentPath = Astro.url.pathname;
const navLinks = [
{ href: '/diensten', label: 'Diensten' },
{ href: '/pakketten', label: 'Pakketten' },
{ href: '/over', label: 'Over Ons' },
{ href: '/blog', label: 'Blog' },
];
function isActive(href: string): boolean {
if (href === '/') return currentPath === '/';
return currentPath.startsWith(href);
}
---
<header id="header" class="fixed top-0 left-0 right-0 z-50 transition-all duration-300">
<nav class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div class="flex h-20 items-center justify-between">
<!-- Logo -->
<a href="/" class="flex items-center gap-2.5 group">
<div class="relative flex h-9 w-9 items-center justify-center rounded-lg bg-gradient-to-br from-accent-400 to-accent-600 transition-transform group-hover:scale-105">
<span class="text-lg font-bold text-slate-950">S</span>
</div>
<span class="text-xl font-bold text-slate-50 tracking-tight">
Site<span class="text-accent-400">Loft</span>
</span>
</a>
<!-- Desktop Navigation -->
<div class="hidden md:flex items-center gap-1">
{navLinks.map((link) => (
<a
href={link.href}
class:list={[
'relative px-4 py-2 text-sm font-medium rounded-lg transition-colors',
isActive(link.href)
? 'text-accent-400'
: 'text-slate-400 hover:text-slate-100',
]}
>
{link.label}
{isActive(link.href) && (
<span class="absolute bottom-0 left-1/2 -translate-x-1/2 h-0.5 w-5 rounded-full bg-accent-400" />
)}
</a>
))}
</div>
<!-- CTA Button -->
<div class="hidden md:flex items-center gap-3">
<a
href="/contact"
class="inline-flex items-center gap-2 rounded-lg bg-accent-500 px-5 py-2.5 text-sm font-semibold text-slate-950 transition-all hover:bg-accent-400 hover:shadow-lg hover:shadow-accent-500/25"
>
Start je project
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M13 7l5 5m0 0l-5 5m5-5H6" />
</svg>
</a>
</div>
<!-- Mobile menu button -->
<button
id="mobile-menu-btn"
class="md:hidden flex items-center justify-center w-10 h-10 rounded-lg text-slate-400 hover:text-slate-100 hover:bg-slate-800/50 transition-colors"
aria-label="Menu openen"
>
<svg id="menu-icon" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16" />
</svg>
<svg id="close-icon" class="h-6 w-6 hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</nav>
<!-- Mobile menu -->
<div id="mobile-menu" class="hidden md:hidden">
<div class="mx-4 mt-2 rounded-2xl glass p-4 space-y-1">
{navLinks.map((link) => (
<a
href={link.href}
class:list={[
'block rounded-lg px-4 py-3 text-sm font-medium transition-colors',
isActive(link.href)
? 'text-accent-400 bg-accent-500/10'
: 'text-slate-300 hover:text-slate-100 hover:bg-slate-800/50',
]}
>
{link.label}
</a>
))}
<div class="pt-2">
<a
href="/contact"
class="block w-full rounded-lg bg-accent-500 px-4 py-3 text-center text-sm font-semibold text-slate-950 transition-colors hover:bg-accent-400"
>
Start je project
</a>
</div>
</div>
</div>
</header>
<script>
// Header scroll effect
const header = document.getElementById('header');
let lastScroll = 0;
window.addEventListener('scroll', () => {
const currentScroll = window.scrollY;
if (currentScroll > 50) {
header?.classList.add('glass', 'shadow-lg', 'shadow-slate-950/50');
} else {
header?.classList.remove('glass', 'shadow-lg', 'shadow-slate-950/50');
}
lastScroll = currentScroll;
});
// Mobile menu toggle
const mobileMenuBtn = document.getElementById('mobile-menu-btn');
const mobileMenu = document.getElementById('mobile-menu');
const menuIcon = document.getElementById('menu-icon');
const closeIcon = document.getElementById('close-icon');
mobileMenuBtn?.addEventListener('click', () => {
const isOpen = !mobileMenu?.classList.contains('hidden');
mobileMenu?.classList.toggle('hidden');
menuIcon?.classList.toggle('hidden');
closeIcon?.classList.toggle('hidden');
mobileMenuBtn.setAttribute('aria-label', isOpen ? 'Menu openen' : 'Menu sluiten');
});
</script>