- Add hamburger icon that morphs to X when menu is open - Full-screen mobile menu overlay with backdrop blur - Staggered fade-in animation for menu items - Desktop navigation unchanged (hidden on mobile) - Close menu via X button, backdrop click, or ESC key 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
122 lines
3.9 KiB
HTML
Executable File
122 lines
3.9 KiB
HTML
Executable File
<div x-data="{ menuOpen: false }" @keydown.escape.window="menuOpen = false">
|
|
<header class="fixed top-0 left-0 right-0 z-sticky bg-surface-0/80 backdrop-blur-md border-b border-border">
|
|
<nav class="container-wide flex items-center justify-between h-16">
|
|
{{/* Logo */}}
|
|
<div class="flex items-center gap-3 group">
|
|
<canvas
|
|
id="logo-canvas"
|
|
hx-preserve="true"
|
|
class="w-8 h-8 cursor-pointer"
|
|
width="32"
|
|
height="32"
|
|
aria-hidden="true"
|
|
@click="window.__pivoine?.visualizer?.nextVisualizer()"
|
|
title="Click to change visualizer"
|
|
></canvas>
|
|
<a
|
|
href="{{ "/" | relURL }}"
|
|
class="text-lg font-medium tracking-tight group-hover:text-accent transition-colors"
|
|
aria-label="{{ .Site.Title }} - Home"
|
|
>
|
|
VALKNAR'S
|
|
</a>
|
|
</div>
|
|
|
|
{{/* Desktop Navigation */}}
|
|
<ul
|
|
class="hidden md:flex items-center gap-8"
|
|
x-data="{ path: window.location.pathname }"
|
|
@htmx:after-settle.window="path = window.location.pathname"
|
|
>
|
|
{{- range .Site.Menus.main }}
|
|
<li>
|
|
<a
|
|
href="{{ .URL }}"
|
|
class="text-sm transition-colors"
|
|
:class="path.startsWith('{{ .URL }}') ? 'text-text-primary border-b border-text-primary' : 'text-text-secondary hover:text-text-primary link-hover'"
|
|
>
|
|
{{ .Name }}
|
|
</a>
|
|
</li>
|
|
{{- end }}
|
|
</ul>
|
|
|
|
{{/* Mobile Hamburger Button */}}
|
|
<button
|
|
class="md:hidden relative w-8 h-8 flex items-center justify-center"
|
|
@click="menuOpen = !menuOpen"
|
|
:aria-expanded="menuOpen"
|
|
aria-label="Toggle menu"
|
|
>
|
|
<div class="hamburger" :class="{ 'is-active': menuOpen }">
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</div>
|
|
</button>
|
|
</nav>
|
|
</header>
|
|
|
|
{{/* Mobile Menu Overlay - Full Screen */}}
|
|
<div
|
|
class="md:hidden fixed inset-0 z-[300]"
|
|
x-show="menuOpen"
|
|
x-cloak
|
|
x-transition:enter="transition ease-out duration-300"
|
|
x-transition:enter-start="opacity-0"
|
|
x-transition:enter-end="opacity-100"
|
|
x-transition:leave="transition ease-in duration-200"
|
|
x-transition:leave-start="opacity-100"
|
|
x-transition:leave-end="opacity-0"
|
|
@click="menuOpen = false"
|
|
>
|
|
{{/* Backdrop */}}
|
|
<div class="absolute inset-0 bg-surface-0/98 backdrop-blur-xl"></div>
|
|
|
|
{{/* Close Button - Top right corner */}}
|
|
<div class="absolute top-0 right-0 h-16 container-wide flex items-center justify-end z-10">
|
|
<button
|
|
class="w-8 h-8 flex items-center justify-center"
|
|
@click.stop="menuOpen = false"
|
|
aria-label="Close menu"
|
|
>
|
|
<div class="hamburger is-active">
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
|
|
{{/* Menu Content */}}
|
|
<nav
|
|
class="relative h-full flex flex-col items-center justify-center"
|
|
x-data="{ path: window.location.pathname }"
|
|
@htmx:after-settle.window="path = window.location.pathname"
|
|
@click.stop
|
|
>
|
|
<ul class="flex flex-col items-center gap-8">
|
|
{{- range $i, $item := .Site.Menus.main }}
|
|
<li
|
|
class="transform transition-all duration-300 ease-out"
|
|
:class="menuOpen ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4'"
|
|
style="transition-delay: {{ mul $i 50 }}ms"
|
|
>
|
|
<a
|
|
href="{{ .URL }}"
|
|
class="text-2xl font-medium tracking-wide transition-colors"
|
|
:class="path.startsWith('{{ .URL }}') ? 'text-text-primary' : 'text-text-secondary hover:text-text-primary'"
|
|
@click="menuOpen = false"
|
|
>
|
|
{{ .Name }}
|
|
</a>
|
|
</li>
|
|
{{- end }}
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
{{/* Spacer for fixed header */}}
|
|
<div class="h-16" aria-hidden="true"></div>
|