88 < div
99 class ="not-prose mx-auto flex min-h-[calc(100dvh-7rem)] max-w-7xl flex-col "
1010 x-data ="{
11- activeTag: 'languages',
1211 query: '',
12+ tagFilter: '',
1313 words() { return this.query.trim().toLowerCase().split(/\s+/).filter(Boolean) },
14- filtering() { return this.query.trim().length > 0 },
14+ textFiltering() { return this.query.trim().length > 0 },
15+ filtering() { return this.textFiltering() || this.tagFilter !== '' },
1516 matchText(text) { return this.words().every(w => text.includes(w)) },
16- rowVisible(el) { return !this.filtering() || this.matchText(el.dataset.search) },
17- sectionVisible(el) { return !this.filtering() || Array.from(el.querySelectorAll('[data-guide]')).some(r => this.matchText(r.dataset.search)) },
18- resultCount() { return Array.from(document.querySelectorAll('[data-guide]')).filter(r => this.matchText(r.dataset.search)).length },
19- init() {
20- const obs = new IntersectionObserver(
21- entries => entries.forEach(e => { if (e.isIntersecting) this.activeTag = e.target.id }),
22- { rootMargin: '-20% 0px -70% 0px', threshold: 0 }
23- );
24- document.querySelectorAll('section[data-tag]').forEach(s => obs.observe(s));
25- }
17+ rowVisible(el) { return !this.textFiltering() || this.matchText(el.dataset.search) },
18+ sectionVisible(el) {
19+ if (this.tagFilter) return el.dataset.tag === this.tagFilter;
20+ if (this.textFiltering()) return Array.from(el.querySelectorAll('[data-guide]')).some(r => this.matchText(r.dataset.search));
21+ return true;
22+ },
23+ resultCount() {
24+ if (this.tagFilter) return document.querySelectorAll('section[data-tag=' + this.tagFilter + '] [data-guide]').length;
25+ return Array.from(document.querySelectorAll('[data-guide]')).filter(r => this.matchText(r.dataset.search)).length;
26+ },
27+ selectTag(tag) { this.tagFilter = this.tagFilter === tag ? '' : tag; this.query = ''; window.scrollTo({ top: 0, behavior: 'smooth' }); },
28+ clear() { this.query = ''; this.tagFilter = ''; }
2629 } "
2730 >
2831 {{- partial "breadcrumbs.html" . }}
5255 < input
5356 type ="search "
5457 x-model ="query "
55- @keydown.escape ="query = '' "
58+ @input ="tagFilter = '' "
59+ @keydown.escape ="clear() "
5660 aria-label ="Filter guides "
5761 placeholder ="Filter guides by name, topic, or tag… "
5862 class ="w-full rounded-xl border border-gray-300 bg-white py-2.5 pr-10 pl-11 text-sm text-gray-900 shadow-sm transition placeholder:text-gray-400 focus:border-blue-400 focus:ring-2 focus:ring-blue-400/40 focus:outline-none dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:placeholder:text-gray-500 "
5963 />
6064 < button
6165 x-show ="query "
6266 x-cloak
63- @click ="query = '' "
67+ @click ="clear() "
6468 aria-label ="Clear filter "
6569 class ="icon-svg icon-sm absolute top-1/2 right-2.5 -translate-y-1/2 rounded-md p-1 text-gray-400 transition hover:bg-gray-100 hover:text-gray-700 dark:hover:bg-gray-800 dark:hover:text-gray-200 "
6670 >
6973 </ div >
7074
7175 < div class ="flex flex-1 gap-16 xl:gap-24 ">
72- <!-- Sticky jump nav (hidden while filtering) -->
73- < nav
74- x-show ="!filtering() "
75- class ="sticky top-20 hidden w-52 flex-none flex-col self-start xl:flex "
76- >
76+ <!-- Sticky topic filter -->
77+ < nav class ="sticky top-20 hidden w-52 flex-none flex-col self-start xl:flex ">
7778 < p class ="mb-3 text-xs font-semibold tracking-widest text-gray-400 uppercase dark:text-gray-500 ">
78- Jump to
79+ Browse
7980 </ p >
81+ < button
82+ type ="button "
83+ @click ="clear() "
84+ class ="flex items-center justify-between py-1.5 text-left text-sm transition-colors "
85+ :class ="!filtering() ? 'text-black dark:text-white font-medium' : 'text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100' "
86+ >
87+ < span class ="flex items-center gap-2.5 ">
88+ < span class ="w-5 "> </ span >
89+ < span > All guides</ span >
90+ </ span >
91+ < span class ="text-xs tabular-nums text-gray-300 dark:text-gray-600 "> {{ len .RegularPagesRecursive }}</ span >
92+ </ button >
8093 {{- range $i, $tag := $tagOrder }}
8194 {{- $tagData := index hugo.Data.tags $tag }}
8295 {{- $pages := where $.RegularPagesRecursive "Params.tags" "intersect" (slice $tag) }}
8396 {{- if $pages }}
84- < a
85- href =" #{{ $tag }} "
86- class =" flex items-center justify-between py-1.5 text-sm transition-colors "
87- : class ="activeTag === '{{ $tag }}' ? 'text-black dark:text-white font-medium' : ' text-gray-500 dark: text-gray-400 hover:text-gray-900 dark:hover:text-gray-100' "
88- @click.prevent =" activeTag = '{{ $tag }}'; document.getElementById('{{ $tag }}').scrollIntoView({ behavior : 'smooth' }) "
97+ < button
98+ type =" button "
99+ @click =" selectTag('{{ $tag }}') "
100+ class ="flex items-center justify-between py-1.5 text-left text-sm transition-colors "
101+ :class =" tagFilter === '{{ $tag }}' ? 'text-black dark:text-white font-medium' : 'text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100' "
89102 >
90103 < span class ="flex items-center gap-2.5 ">
91104 < span class ="w-5 text-xs tabular-nums text-gray-300 dark:text-gray-600 ">
94107 < span > {{ $tagData.title }}</ span >
95108 </ span >
96109 < span class ="text-xs tabular-nums text-gray-300 dark:text-gray-600 "> {{ len $pages }}</ span >
97- </ a >
110+ </ button >
98111 {{- end }}
99112 {{- end }}
100113 </ nav >
112125 of {{ len .RegularPagesRecursive }} guides
113126 </ p >
114127 < button
115- @click ="query = '' "
128+ @click ="clear() "
116129 class ="text-sm font-medium text-blue-600 transition hover:underline dark:text-blue-400 "
117130 >
118131 Clear filter
@@ -145,21 +158,18 @@ <h2 class="text-2xl font-bold">{{ $tagData.title }}</h2>
145158 {{- range .Params.tags }}{{ $tagTitles = $tagTitles | append (index hugo.Data.tags .).title }}{{ end }}
146159 {{- $search := lower (printf "%s %s %s %s" .Title .Summary (delimit .Params.tags " ") (delimit $tagTitles " ")) }}
147160 {{- $search = $search | replaceRE "\\s+" " " }}
148- < a
149- href ="{{ .Permalink }} "
161+ < div
150162 data-guide
151163 data-search ="{{ $search }} "
152164 x-show ="rowVisible($el) "
153- class ="group -mx-3 grid grid-cols-[5fr_6fr_auto ] items-start gap-6 rounded-lg px-3 py-4 transition-colors hover:bg-gray-50 dark:hover:bg-gray-900 "
165+ class ="grid grid-cols-[5fr_6fr ] items-start gap-6 py-4 "
154166 >
155- < span class ="font-medium leading-snug text-gray-900 transition-colors group-hover:text-blue-600 dark:text-gray-100 dark:group-hover:text-blue-400 "> {{ .Title }}</ span >
167+ < a
168+ href ="{{ .Permalink }} "
169+ class ="font-medium leading-snug text-gray-900 hover:underline dark:text-gray-100 "
170+ > {{ .Title }}</ a >
156171 < span class ="text-sm leading-relaxed text-gray-500 dark:text-gray-400 "> {{ .Summary }}</ span >
157- < span
158- class ="icon-svg icon-sm mt-0.5 self-center text-gray-300 opacity-0 transition-all duration-200 group-hover:translate-x-0.5 group-hover:text-blue-600 group-hover:opacity-100 dark:text-gray-600 dark:group-hover:text-blue-400 "
159- >
160- {{ partialCached "icon" "arrow-right" "arrow-right" }}
161- </ span >
162- </ a >
172+ </ div >
163173 {{- end }}
164174 </ div >
165175 </ section >
@@ -179,7 +189,7 @@ <h2 class="text-2xl font-bold">{{ $tagData.title }}</h2>
179189 No guides match “< span class ="font-medium text-gray-700 dark:text-gray-200 " x-text ="query "> </ span > ”.
180190 </ p >
181191 < button
182- @click ="query = '' "
192+ @click ="clear() "
183193 class ="text-sm font-medium text-blue-600 transition hover:underline dark:text-blue-400 "
184194 >
185195 Clear filter
0 commit comments