diff options
| author | Danilo M. <danix@danix.xyz> | 2026-04-22 12:42:56 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-04-22 12:42:56 +0200 |
| commit | 631547a75142326a7c71bdf123e1475217a5ad73 (patch) | |
| tree | f3cfef6b3c5b42bf626fc823ddcf63b8dcf4cdbb /layouts/partials/hamburger-menu.html | |
| parent | 77ccbe72fad5a4870185fff374f75471c16a9043 (diff) | |
| download | danixxyz-theme-631547a75142326a7c71bdf123e1475217a5ad73.tar.gz danixxyz-theme-631547a75142326a7c71bdf123e1475217a5ad73.zip | |
chore: replace with extracted danix.xyz-hacker theme (danix2-hugo-theme)
Diffstat (limited to 'layouts/partials/hamburger-menu.html')
| -rw-r--r-- | layouts/partials/hamburger-menu.html | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/layouts/partials/hamburger-menu.html b/layouts/partials/hamburger-menu.html new file mode 100644 index 0000000..5d8d8ed --- /dev/null +++ b/layouts/partials/hamburger-menu.html @@ -0,0 +1,125 @@ +<!-- Mobile menu overlay (Alpine.js controlled) --> +<div + x-cloak + x-data="{ menuOpen: false }" + @toggle-menu.window="menuOpen = !menuOpen" + @keydown.escape.window="menuOpen = false" + :class="{ 'opacity-0 invisible': !menuOpen, 'opacity-100 visible': menuOpen }" + class="fixed inset-0 bg-black/50 backdrop-blur transition-all duration-300 z-40" + :aria-hidden="!menuOpen" + @click="if ($event.target === $el) menuOpen = false" +> + <div + class="fixed top-0 right-0 h-screen w-full max-w-sm bg-bg border-l border-border overflow-y-auto transform transition-transform duration-300 z-50" + :class="{ 'translate-x-full': !menuOpen, 'translate-x-0': menuOpen }" + > + <!-- Close button --> + <div class="flex items-center justify-between p-6 border-b border-border"> + <span class="font-bold text-lg text-accent font-oxanium">Menu</span> + <button + @click="menuOpen = false" + aria-label="{{ i18n "closeMenu" }}" + class="p-2 hover:bg-surface rounded transition-colors" + > + <i data-feather="x" class="w-5 h-5"></i> + </button> + </div> + + <!-- Menu items --> + <nav class="p-6" role="navigation" aria-label="{{ i18n "mainMenu" }}"> + {{ $currentPath := strings.TrimSuffix "/" .RelPermalink }} + {{ range .Site.Menus.main }} + {{ $menuPath := strings.TrimSuffix "/" .URL }} + {{ $isActive := eq $menuPath $currentPath }} + <a + href="{{ .URL }}" + @click="menuOpen = false" + class="block py-4 text-lg font-medium transition-colors border-b border-border/30 {{ if $isActive }}text-accent font-bold{{ else }}hover:text-accent{{ end }}" + {{ if $isActive }}aria-current="page"{{ end }} + > + {{ i18n .Name }} + </a> + {{ end }} + </nav> + + <!-- Mobile search bar --> + <div class="p-6 border-b border-border" x-data="mobileSearch()"> + <label for="search-input-mobile" class="sr-only"> + {{ i18n "searchPlaceholder" }} + </label> + <input + id="search-input-mobile" + type="text" + :value="searchQuery" + @input="filterArticles($el.value); ensureIndexLoaded()" + placeholder="{{ i18n "searchPlaceholder" }}" + class="w-full px-4 py-2 border-2 border-border rounded focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent bg-bg text-text text-sm" + aria-describedby="mobile-search-results" + /> + + <!-- Mobile search results --> + <div id="mobile-search-results" class="mt-3 space-y-2" x-show="filteredArticles.length > 0" role="region" aria-live="polite"> + <template x-for="article in filteredArticles" :key="article.url"> + <div class="p-3 border-l-4 border-accent bg-bg/50 hover:bg-bg/70 transition-colors rounded text-sm"> + <a :href="article.url" @click="menuOpen = false" class="block focus:outline-none focus:ring-2 focus:ring-accent rounded px-1 py-1"> + <h4 class="font-bold text-accent" x-text="article.title"></h4> + <p class="text-xs text-text-dim mt-0.5" x-text="article.date"></p> + </a> + </div> + </template> + </div> + + <!-- Empty state --> + <div + x-show="searchQuery && filteredArticles.length === 0" + class="mt-3 text-sm text-text-dim" + role="status" + > + {{ i18n "noSearchResults" }} + </div> + </div> + + <!-- Language switcher --> + <div class="p-6"> + <div class="text-sm text-text-dim mb-3">{{ i18n "language" }}</div> + <div class="flex gap-2"> + {{ $currentLang := .Page.Language }} + {{ $currentPath := .RelPermalink }} + {{ range .Site.Languages }} + {{ $langCode := .Lang }} + {{ $langName := .LanguageName }} + {{ $current := eq $langCode $currentLang }} + <!-- Build the translated URL by replacing language prefix --> + {{ $url := $currentPath }} + {{ if eq $langCode "en" }} + {{ if hasPrefix $currentPath "/it/" }} + {{ $url = strings.TrimPrefix "/it" $currentPath }} + {{ end }} + {{ else }} + {{ if not (hasPrefix $currentPath "/it/") }} + {{ $url = printf "/it%s" $currentPath }} + {{ end }} + {{ end }} + <a + href="{{ $url }}" + @click="menuOpen = false" + class="flex-1 py-2 px-3 text-center rounded transition-colors {{ if $current }}bg-accent text-white{{ else }}bg-surface hover:bg-surface/80{{ end }}" + > + {{ $langName }} + </a> + {{ end }} + </div> + </div> + + </div> +</div> + +<script> + // Close menu before page navigation to prevent flicker + window.addEventListener('beforeunload', () => { + const overlay = document.querySelector('[x-data*="menuOpen"]'); + if (overlay && overlay.__x) { + overlay.__x.$data.menuOpen = false; + } + }); +</script> |
