blob: 248b172773ca83bd96982de70f0950144403f3aa (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
<!-- 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 }}
{{ $isExternal := .Params.external }}
<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 }}
{{ if $isExternal }}target="_blank" rel="noopener noreferrer"{{ end }}
>
{{ if $isExternal }}{{ .Name }}{{ else }}{{ i18n .Name }}{{ end }}
{{ if $isExternal }}<span class="sr-only">{{ i18n "opensInNewTab" }}</span>{{ end }}
</a>
{{ if .HasChildren }}
<div class="pl-4 border-l-2 border-accent/40 ml-2">
{{ range .Children }}
{{ $childExternal := .Params.external }}
<a
href="{{ .URL }}"
@click="menuOpen = false"
class="block py-3 text-base text-text-dim hover:text-accent transition-colors rounded focus:outline-none focus:ring-2 focus:ring-accent"
{{ if $childExternal }}target="_blank" rel="noopener noreferrer"{{ end }}
>
{{ if $childExternal }}{{ .Name }}{{ else }}{{ i18n .Name }}{{ end }}
</a>
{{ end }}
</div>
{{ end }}
{{ 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>
|