Skip to content

Commit 2ced987

Browse files
Copilotbrunoborges
andcommitted
Replace category filter pills with compact dropdown matching JDK dropdown design
Co-authored-by: brunoborges <129743+brunoborges@users.noreply.github.com>
1 parent b7788e6 commit 2ced987

File tree

4 files changed

+75
-105
lines changed

4 files changed

+75
-105
lines changed

site/app.js

Lines changed: 55 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,11 @@
199199
};
200200

201201
/* ==========================================================
202-
2. Category Filter Pills (homepage)
202+
2. Category + JDK Dropdown Filters (homepage)
203203
========================================================== */
204204
const initFilters = () => {
205-
const pills = document.querySelectorAll('#categoryFilter .filter-pill');
206205
const cards = document.querySelectorAll('.tip-card');
207-
if (!pills.length || !cards.length) return;
206+
if (!cards.length) return;
208207

209208
let activeCategory = null;
210209
let activeJdk = null;
@@ -234,34 +233,12 @@
234233
}
235234
};
236235

237-
pills.forEach(pill => {
238-
pill.addEventListener('click', () => {
239-
const category = pill.dataset.filter || 'all';
240-
const wasActive = pill.classList.contains('active');
241-
242-
// Update active pill (toggle off if re-clicked)
243-
pills.forEach(p => p.classList.remove('active'));
244-
if (!wasActive) pill.classList.add('active');
245-
246-
activeCategory = (!wasActive && category !== 'all') ? category : null;
247-
248-
// Update URL hash to reflect active filter
249-
if (activeCategory) {
250-
history.replaceState(null, '', '#' + activeCategory);
251-
} else {
252-
history.replaceState(null, '', window.location.pathname + window.location.search);
253-
}
254-
255-
applyFilters();
256-
});
257-
});
258-
259-
// JDK Dropdown
260-
const jdkDropdown = document.getElementById('jdkDropdown');
261-
if (jdkDropdown) {
262-
const toggleBtn = jdkDropdown.querySelector('.jdk-dropdown-toggle');
263-
const labelEl = jdkDropdown.querySelector('.jdk-label');
264-
const list = jdkDropdown.querySelector('ul');
236+
// Generic helper to wire up a dropdown
237+
const initDropdown = (dropdownEl, onSelect) => {
238+
if (!dropdownEl) return;
239+
const toggleBtn = dropdownEl.querySelector('.jdk-dropdown-toggle');
240+
const labelEl = dropdownEl.querySelector('.jdk-label');
241+
const list = dropdownEl.querySelector('ul');
265242

266243
const openDropdown = () => {
267244
list.style.display = 'block';
@@ -273,6 +250,12 @@
273250
toggleBtn.setAttribute('aria-expanded', 'false');
274251
};
275252

253+
const selectItem = (li) => {
254+
list.querySelectorAll('li').forEach(l => l.classList.remove('active'));
255+
li.classList.add('active');
256+
if (labelEl) labelEl.textContent = li.textContent.trim();
257+
};
258+
276259
toggleBtn.addEventListener('click', (e) => {
277260
e.stopPropagation();
278261
list.style.display === 'block' ? closeDropdown() : openDropdown();
@@ -287,33 +270,55 @@
287270
li.addEventListener('click', (e) => {
288271
e.stopPropagation();
289272
closeDropdown();
273+
selectItem(li);
274+
onSelect(li, toggleBtn);
275+
});
276+
});
290277

291-
const version = li.dataset.jdkFilter;
292-
list.querySelectorAll('li').forEach(l => l.classList.remove('active'));
293-
li.classList.add('active');
278+
return { closeDropdown, setActive: (value) => {
279+
const target = list.querySelector(`li[data-filter="${value}"]`);
280+
if (target) {
281+
selectItem(target);
282+
toggleBtn.classList.toggle('has-filter', value !== 'all');
283+
}
284+
}};
285+
};
294286

295-
activeJdk = version !== 'all' ? version : null;
296-
if (labelEl) labelEl.textContent = li.textContent.trim();
297-
toggleBtn.classList.toggle('has-filter', !!activeJdk);
287+
// Category dropdown
288+
const categoryDropdown = document.getElementById('categoryDropdown');
289+
const catDropdownCtrl = initDropdown(categoryDropdown, (li, toggleBtn) => {
290+
const category = li.dataset.filter;
291+
activeCategory = category !== 'all' ? category : null;
292+
toggleBtn.classList.toggle('has-filter', !!activeCategory);
293+
if (activeCategory) {
294+
history.replaceState(null, '', '#' + activeCategory);
295+
} else {
296+
history.replaceState(null, '', window.location.pathname + window.location.search);
297+
}
298+
applyFilters();
299+
});
298300

299-
applyFilters();
300-
});
301-
});
302-
}
301+
// JDK dropdown
302+
const jdkDropdown = document.getElementById('jdkDropdown');
303+
initDropdown(jdkDropdown, (li, toggleBtn) => {
304+
const version = li.dataset.jdkFilter;
305+
activeJdk = version !== 'all' ? version : null;
306+
toggleBtn.classList.toggle('has-filter', !!activeJdk);
307+
applyFilters();
308+
});
303309

304310
// Apply filter from a given category string (or "all" / empty for no filter)
305311
const applyHashFilter = (category) => {
306-
const target = category
307-
? document.querySelector(`#categoryFilter .filter-pill[data-filter="${category}"]`)
308-
: null;
309-
if (target) {
310-
target.click();
311-
// Scroll the filter section into view
312+
if (category && catDropdownCtrl) {
313+
catDropdownCtrl.setActive(category);
314+
activeCategory = category;
315+
applyFilters();
312316
const section = document.getElementById('all-comparisons');
313317
if (section) section.scrollIntoView({ behavior: 'smooth' });
314-
} else {
315-
const allButton = document.querySelector('#categoryFilter .filter-pill[data-filter="all"]');
316-
if (allButton) allButton.click();
318+
} else if (catDropdownCtrl) {
319+
catDropdownCtrl.setActive('all');
320+
activeCategory = null;
321+
applyFilters();
317322
}
318323
};
319324

site/styles.css

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -406,46 +406,6 @@ nav {
406406
margin-bottom: 16px;
407407
}
408408

409-
/* ---------- Filter Pills ---------- */
410-
.filter-pills {
411-
display: flex;
412-
flex-wrap: wrap;
413-
gap: 8px;
414-
justify-content: center;
415-
align-items: center;
416-
margin-bottom: 40px;
417-
}
418-
419-
.filter-label {
420-
font-size: 0.82rem;
421-
font-weight: 500;
422-
color: var(--text-muted);
423-
padding: 7px 8px 7px 0;
424-
}
425-
426-
.filter-pill {
427-
padding: 7px 16px;
428-
border-radius: 999px;
429-
font-size: 0.82rem;
430-
font-weight: 500;
431-
border: 1px solid var(--border);
432-
background: var(--surface);
433-
color: var(--text-muted);
434-
cursor: pointer;
435-
transition: all 0.2s;
436-
}
437-
438-
.filter-pill:hover {
439-
border-color: var(--border-light);
440-
color: var(--text);
441-
}
442-
443-
.filter-pill.active {
444-
background: var(--accent);
445-
border-color: var(--accent);
446-
color: #fff;
447-
}
448-
449409
/* ---------- Tips / Card Grid ---------- */
450410
.tips-grid {
451411
display: grid;

templates/index.html

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -233,22 +233,26 @@ <h1>{{site.tagline_line1}}<br><span class="gradient">{{site.tagline_line2}}</spa
233233
<h2 class="section-title">{{site.allComparisons}}</h2>
234234
<span class="section-badge">{{site.snippetsBadge}}</span>
235235
</div>
236-
<div class="filter-pills" id="categoryFilter">
237-
<span class="filter-label">{{filters.show}}</span>
238-
<button class="filter-pill" data-filter="all">{{filters.all}}</button>
239-
<button class="filter-pill" data-filter="language">Language</button>
240-
<button class="filter-pill" data-filter="collections">Collections</button>
241-
<button class="filter-pill" data-filter="strings">Strings</button>
242-
<button class="filter-pill" data-filter="streams">Streams</button>
243-
<button class="filter-pill" data-filter="concurrency">Concurrency</button>
244-
<button class="filter-pill" data-filter="io">I/O</button>
245-
<button class="filter-pill" data-filter="errors">Errors</button>
246-
<button class="filter-pill" data-filter="datetime">Date/Time</button>
247-
<button class="filter-pill" data-filter="security">Security</button>
248-
<button class="filter-pill" data-filter="tooling">Tooling</button>
249-
<button class="filter-pill" data-filter="enterprise">Enterprise</button>
250-
</div>
251236
<div class="view-toggle-wrap">
237+
<div class="jdk-dropdown" id="categoryDropdown">
238+
<button class="jdk-dropdown-toggle" aria-haspopup="listbox" aria-expanded="false">
239+
{{filters.category}} <span class="jdk-label">{{filters.all}}</span> <span class="dropdown-caret"></span>
240+
</button>
241+
<ul role="listbox">
242+
<li data-filter="all" class="active">{{filters.all}}</li>
243+
<li data-filter="language">Language</li>
244+
<li data-filter="collections">Collections</li>
245+
<li data-filter="strings">Strings</li>
246+
<li data-filter="streams">Streams</li>
247+
<li data-filter="concurrency">Concurrency</li>
248+
<li data-filter="io">I/O</li>
249+
<li data-filter="errors">Errors</li>
250+
<li data-filter="datetime">Date/Time</li>
251+
<li data-filter="security">Security</li>
252+
<li data-filter="tooling">Tooling</li>
253+
<li data-filter="enterprise">Enterprise</li>
254+
</ul>
255+
</div>
252256
<div class="jdk-dropdown" id="jdkDropdown">
253257
<button class="jdk-dropdown-toggle" aria-haspopup="listbox" aria-expanded="false">
254258
{{filters.jdk}} <span class="jdk-label">{{filters.all}}</span> <span class="dropdown-caret"></span>

translations/strings/en.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ filters:
3434
show: 'Show:'
3535
all: All
3636
jdk: 'JDK:'
37+
category: 'Category:'
3738
difficulty:
3839
beginner: Beginner
3940
intermediate: Intermediate

0 commit comments

Comments
 (0)