src/components/nav/NavMega.astro
---
/**
* NavMega — navigatiebalk met mega-dropdown (links + featured card) en mobiele drawer.
*
* Props:
* - logo?: string
* - logoHref?: string
* - megaLabel?: string (label van het item met mega-dropdown)
* - megaItems?: Array<{ label: string; desc: string; href: string }>
* - featured?: { label: string; desc: string; href: string; linkLabel: string; image: string; imageAlt: string }
* - links?: Array<{ label: string; href: string }> (overige top-level links)
* - secondaryCta?: { label: string; href: string }
* - primaryCta?: { label: string; href: string }
*/
interface MegaItem { label: string; desc: string; href: string; }
interface Props {
logo?: string;
logoHref?: string;
megaLabel?: string;
megaItems?: MegaItem[];
featured?: { label: string; desc: string; href: string; linkLabel: string; image: string; imageAlt: string };
links?: { label: string; href: string }[];
secondaryCta?: { label: string; href: string };
primaryCta?: { label: string; href: string };
}
const {
logo = 'Merk',
logoHref = '/',
megaLabel = 'Diensten',
megaItems = [
{ label: 'Item één', desc: 'Korte omschrijving van de dienst', href: '#' },
{ label: 'Item twee', desc: 'Korte omschrijving van de dienst', href: '#' },
{ label: 'Item drie', desc: 'Korte omschrijving van de dienst', href: '#' },
{ label: 'Item vier', desc: 'Korte omschrijving van de dienst', href: '#' },
],
featured = {
label: 'Uitgelicht',
desc: 'Korte introductie van het uitgelichte item.',
href: '#',
linkLabel: 'Bekijk',
image: '/img/ext/photo-1677442135703-1787eea5ce01-w400-0cba48.jpg',
imageAlt: 'Uitgelicht',
},
links = [
{ label: 'Werk', href: '#' },
{ label: 'Over ons', href: '#' },
{ label: 'Blog', href: '#' },
],
secondaryCta = { label: 'Inloggen', href: '#' },
primaryCta = { label: 'Gratis gesprek', href: '#' },
} = Astro.props;
---
<header class="bl-section nm" data-component="nav-mega">
<nav class="nm__nav">
<div class="bl-inner nm__inner">
<a href={logoHref} class="nm__logo">
<span class="nm__logo-text">{logo}</span>
</a>
<ul class="nm__menu" role="menubar">
<li class="nm__item nm__item--has-children" role="none">
<button class="nm__link nm__link--toggle" aria-haspopup="true" aria-expanded="false" data-menu-index="0">
{megaLabel}
<svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M2 4l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path></svg>
</button>
<div class="nm__dropdown" role="menu" aria-label={megaLabel}>
<div class="nm__dropdown-inner">
<div class="nm__dropdown-links">
{megaItems.map(item => (
<a href={item.href} class="nm__dropdown-item" role="menuitem">
<div class="nm__dropdown-text">
<span class="nm__dropdown-label">{item.label}</span>
<span class="nm__dropdown-desc">{item.desc}</span>
</div>
</a>
))}
</div>
<div class="nm__featured">
<img data-allow-img src={featured.image} alt={featured.imageAlt} class="nm__featured-img" loading="lazy" decoding="async" />
<div class="nm__featured-body">
<p class="nm__featured-label">{featured.label}</p>
<p class="nm__featured-desc">{featured.desc}</p>
<a href={featured.href} class="nm__featured-link">{featured.linkLabel}</a>
</div>
</div>
</div>
</div>
</li>
{links.map(l => (
<li class="nm__item" role="none">
<a href={l.href} class="nm__link">{l.label}</a>
</li>
))}
</ul>
<div class="nm__actions">
<a href={secondaryCta.href} class="nm__action-secondary">{secondaryCta.label}</a>
<a href={primaryCta.href} class="nm__action-primary">{primaryCta.label}</a>
</div>
<button class="nm__hamburger" aria-label="Menu" id="nm-hamburger">
<span></span><span></span><span></span>
</button>
</div>
</nav>
<div class="nm__drawer" id="nm-drawer" aria-hidden="true">
<div class="nm__drawer-section">
<p class="nm__drawer-heading">{megaLabel}</p>
{megaItems.map(item => <a href={item.href} class="nm__drawer-link">{item.label}</a>)}
</div>
{links.map(l => (
<div class="nm__drawer-section">
<p class="nm__drawer-heading">{l.label}</p>
<a href={l.href} class="nm__drawer-link">{l.label}</a>
</div>
))}
<div class="nm__drawer-ctas">
<a href={secondaryCta.href} class="nm__action-secondary">{secondaryCta.label}</a>
<a href={primaryCta.href} class="nm__action-primary" style="display:block;text-align:center">{primaryCta.label}</a>
</div>
</div>
</header>
<style>
.nm{position:relative;z-index:100;padding-block:0}
.nm__nav{background:var(--color-bg, #fff);border-bottom:1px solid rgba(0,0,0,.07)}
.nm__inner{height:64px;display:flex;align-items:center;gap:2rem}
.nm__logo{text-decoration:none;flex-shrink:0}
.nm__logo-img{height:32px}
.nm__logo-text{font-size:1.125rem;font-weight:800;color:var(--color-primary, #0a0a0a);letter-spacing:-.03em}
.nm__menu{display:flex;list-style:none;gap:0;flex:1}
.nm__item{position:relative}
.nm__link{display:flex;align-items:center;gap:.35rem;padding:0 1rem;height:64px;font-size:.9rem;font-weight:500;color:var(--color-primary, #0a0a0a);text-decoration:none;background:none;border:none;cursor:pointer;white-space:nowrap;transition:color .15s}
.nm__link:hover{color:var(--color-accent, #6366f1)}
.nm__link--toggle svg{transition:transform .2s}
.nm__link--toggle.is-open svg{transform:rotate(180deg)}
.nm__dropdown{position:absolute;top:calc(100% + 8px);left:-1rem;min-width:520px;background:#fff;border:1px solid rgba(0,0,0,.07);border-radius:calc(var(--radius, .5rem) * 1.5);box-shadow:0 20px 40px #0000001a;padding:1rem;display:none;z-index:200}
.nm__dropdown.is-open{display:block}
.nm__dropdown-inner{display:grid;grid-template-columns:1fr auto;gap:1rem}
.nm__dropdown-links{display:flex;flex-direction:column;gap:.25rem}
.nm__dropdown-item{display:flex;align-items:flex-start;gap:.75rem;padding:.625rem .75rem;border-radius:var(--radius, .5rem);text-decoration:none;transition:background .15s}
.nm__dropdown-item:hover{background:#f5f5f7}
.nm__dropdown-icon{width:36px;height:36px;background:color-mix(in srgb,var(--color-accent, #6366f1) 10%,transparent);color:var(--color-accent, #6366f1);border-radius:.5rem;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:1rem}
.nm__dropdown-label{display:block;font-size:.875rem;font-weight:600;color:var(--color-primary, #0a0a0a)}
.nm__dropdown-desc{display:block;font-size:.8125rem;color:var(--color-muted, #6b7280);margin-top:.125rem}
.nm__featured{width:200px;background:#f5f5f7;border-radius:var(--radius, .5rem);overflow:hidden;display:flex;flex-direction:column}
.nm__featured-img{width:100%;height:120px;object-fit:cover}
.nm__featured-body{padding:.875rem}
.nm__featured-label{font-size:.875rem;font-weight:700;color:var(--color-primary, #0a0a0a);margin-bottom:.25rem}
.nm__featured-desc{font-size:.8rem;color:var(--color-muted, #6b7280);margin-bottom:.625rem}
.nm__featured-link{font-size:.8rem;font-weight:700;color:var(--color-accent, #6366f1);text-decoration:none}
.nm__actions{display:flex;align-items:center;gap:.75rem;margin-left:auto;flex-shrink:0}
.nm__action-secondary{font-size:.875rem;font-weight:600;color:var(--color-primary, #0a0a0a);text-decoration:none;opacity:.7;transition:opacity .15s}
.nm__action-secondary:hover{opacity:1}
.nm__action-primary{font-size:.875rem;font-weight:700;background:var(--color-accent, #6366f1);color:#fff;padding:.5rem 1.25rem;border-radius:var(--radius, .5rem);text-decoration:none;transition:filter .15s}
.nm__action-primary:hover{filter:brightness(1.1)}
.nm__hamburger{display:none;flex-direction:column;gap:5px;background:none;border:none;cursor:pointer;padding:.5rem;margin-left:auto}
.nm__hamburger span{display:block;width:22px;height:2px;background:var(--color-primary, #0a0a0a);border-radius:2px}
.nm__drawer{display:none;background:var(--color-bg, #fff);border-top:1px solid rgba(0,0,0,.07);padding:1.5rem;flex-direction:column;gap:1.5rem}
.nm__drawer.is-open{display:flex}
.nm__drawer-heading{font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--color-muted, #6b7280);margin-bottom:.5rem}
.nm__drawer-link{display:block;padding:.5rem 0;color:var(--color-primary, #0a0a0a);text-decoration:none;font-size:.9375rem;font-weight:500;border-bottom:1px solid rgba(0,0,0,.05)}
.nm__drawer-ctas{display:flex;flex-direction:column;gap:.75rem;padding-top:.5rem}
@media (max-width: 900px) {
.nm__menu, .nm__actions { display: none; }
.nm__hamburger { display: flex; }
}
</style>
<script>
// Mega-dropdown toggle (klik) + mobiele drawer.
const toggles = document.querySelectorAll('[data-component="nav-mega"] .nm__link--toggle');
toggles.forEach(t => {
t.addEventListener('click', (e) => {
e.preventDefault();
const dd = t.parentElement?.querySelector('.nm__dropdown');
const open = dd?.classList.toggle('is-open');
t.classList.toggle('is-open', !!open);
t.setAttribute('aria-expanded', String(!!open));
});
});
const ham = document.getElementById('nm-hamburger');
const drawer = document.getElementById('nm-drawer');
ham?.addEventListener('click', () => {
const open = drawer?.classList.toggle('is-open');
drawer?.setAttribute('aria-hidden', String(!open));
});
</script>