From 88f2efb7de3175abb4798edfa8fa8b4a17f9ea56 Mon Sep 17 00:00:00 2001 From: santoslgl01-web Date: Sun, 26 Apr 2026 18:14:34 -0300 Subject: [PATCH 1/3] fix: show active filter indicators Resolves #145 --- docs/script.js | 120 +++++++++++++++++++++++++++++++++++++------- docs/styles.css | 46 +++++++++++++++++ layouts/layout.html | 5 ++ 3 files changed, 152 insertions(+), 19 deletions(-) diff --git a/docs/script.js b/docs/script.js index ce656ebf..15947154 100644 --- a/docs/script.js +++ b/docs/script.js @@ -743,6 +743,7 @@ function updateVisibilityAndSort() { renderCards(sortedUsers); updateCounts(sortedUsers); updateResultsMessage(sortedUsers); + updateActiveFilterIndicators(); } /** @@ -1030,6 +1031,105 @@ function updateResultsMessage(sortedUsers) { } } +// ============================================================================ +// ACTIVE FILTER INDICATORS +// ============================================================================ +const DEFAULT_FILTER_VALUES = { + searchInput: '', + sortBy: 'followers-desc', + followersFilter: '0', + maxFollowersFilter: '999999999', + minReposFilter: '0', + maxReposFilter: '999999', + minForksFilter: '0', + maxForksFilter: '999999', + sponsorsFilter: 'any', + sponsoringFilter: 'any', + avatarAgeFilter: 'any', + minStarsFilter: '0', + languageFilter: '', + lastRepoActivityFilter: 'any', + lastCommitFilter: 'any', +}; + +const FILTER_LABELS = { + searchInput: 'Search', + sortBy: 'Sort', + followersFilter: 'Min followers', + maxFollowersFilter: 'Max followers', + minReposFilter: 'Min repos', + maxReposFilter: 'Max repos', + minForksFilter: 'Min forks', + maxForksFilter: 'Max forks', + sponsorsFilter: 'Sponsors', + sponsoringFilter: 'Sponsoring', + avatarAgeFilter: 'Avatar updated', + minStarsFilter: 'Min stars', + languageFilter: 'Language', + lastRepoActivityFilter: 'Repo activity', + lastCommitFilter: 'Public commit', +}; + +function getControlDisplayValue(element) { + if (!element) return ''; + if (element.tagName === 'SELECT') { + return ( + element.options[element.selectedIndex]?.textContent.trim() || element.value + ); + } + return element.value.trim(); +} + +function getActiveFilterSummaries() { + return Object.entries(DEFAULT_FILTER_VALUES) + .map(([id, defaultValue]) => { + const element = document.getElementById(id); + if (!element || element.value === defaultValue) return null; + return `${FILTER_LABELS[id]}: ${getControlDisplayValue(element)}`; + }) + .filter(Boolean); +} + +function renderActiveFilterIndicator(container) { + if (!container) return; + + const activeFilters = getActiveFilterSummaries(); + if (!activeFilters.length) { + container.style.display = 'none'; + container.innerHTML = ''; + return; + } + + container.style.display = 'flex'; + container.innerHTML = ''; + + const label = document.createElement('span'); + label.className = 'active-filters-label'; + label.textContent = 'Active:'; + container.appendChild(label); + + activeFilters.forEach((filterText) => { + const badge = document.createElement('span'); + badge.className = 'active-filter-badge'; + badge.textContent = filterText; + container.appendChild(badge); + }); + + const clearButton = document.createElement('button'); + clearButton.type = 'button'; + clearButton.className = 'active-filters-clear'; + clearButton.textContent = 'Clear all'; + clearButton.addEventListener('click', resetFilters); + container.appendChild(clearButton); +} + +function updateActiveFilterIndicators() { + renderActiveFilterIndicator(document.getElementById('activeFiltersSummary')); + renderActiveFilterIndicator( + document.getElementById('activeFiltersSummaryDesktop'), + ); +} + // ============================================================================ // RESET FILTERS // ============================================================================ @@ -1037,25 +1137,7 @@ function updateResultsMessage(sortedUsers) { * Reset all filters to default values */ function resetFilters() { - const defaults = { - searchInput: '', - sortBy: 'followers-desc', - followersFilter: '0', - maxFollowersFilter: '999999999', - minReposFilter: '0', - maxReposFilter: '999999', - minForksFilter: '0', - maxForksFilter: '999999', - sponsorsFilter: 'any', - sponsoringFilter: 'any', - avatarAgeFilter: 'any', - minStarsFilter: '0', - languageFilter: '', - lastRepoActivityFilter: 'any', - lastCommitFilter: 'any', - }; - - Object.entries(defaults).forEach(([id, value]) => { + Object.entries(DEFAULT_FILTER_VALUES).forEach(([id, value]) => { const element = document.getElementById(id); if (element) element.value = value; }); diff --git a/docs/styles.css b/docs/styles.css index 67148f67..b51c3f03 100644 --- a/docs/styles.css +++ b/docs/styles.css @@ -330,6 +330,52 @@ h1 { display: none; } +.active-filters-summary { + display: none; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 6px; + margin-top: 8px; +} + +.active-filters-label { + font-weight: 600; +} + +.active-filter-badge { + padding: 3px 8px; + background: rgba(255, 255, 255, 0.2); + border: 1px solid rgba(255, 255, 255, 0.35); + border-radius: 999px; +} + +.active-filters-summary-desktop .active-filter-badge { + background: #eef2ff; + border-color: #c7d2fe; + color: #4f46e5; +} + +.active-filters-clear { + padding: 3px 8px; + border: 0; + border-radius: 999px; + background: rgba(255, 100, 100, 0.28); + color: inherit; + cursor: pointer; + font: inherit; + font-weight: 600; +} + +.active-filters-clear:hover { + background: rgba(255, 100, 100, 0.45); +} + +.active-filters-summary-desktop .active-filters-clear { + background: #fee2e2; + color: #b91c1c; +} + /* ============================================================================ */ /* LOADING STATE */ /* ============================================================================ */ diff --git a/layouts/layout.html b/layouts/layout.html index c3ad7786..863a977e 100644 --- a/layouts/layout.html +++ b/layouts/layout.html @@ -368,6 +368,7 @@

🔍 Find Your Favorite Developer

Showing 0 of 0 developers +
@@ -453,6 +454,10 @@ Showing 0 of 0 developers +
From d63d236be547c169ae12a935b8d71a5379879101 Mon Sep 17 00:00:00 2001 From: santoslgl01-web Date: Sun, 26 Apr 2026 18:17:15 -0300 Subject: [PATCH 2/3] fix: avoid innerHTML in filter indicator --- docs/script.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/script.js b/docs/script.js index 15947154..c2cf42cc 100644 --- a/docs/script.js +++ b/docs/script.js @@ -1096,12 +1096,12 @@ function renderActiveFilterIndicator(container) { const activeFilters = getActiveFilterSummaries(); if (!activeFilters.length) { container.style.display = 'none'; - container.innerHTML = ''; + container.replaceChildren(); return; } container.style.display = 'flex'; - container.innerHTML = ''; + container.replaceChildren(); const label = document.createElement('span'); label.className = 'active-filters-label'; From 3c7c03cbd07f0dbee1efe3917f4194ac3136a6bf Mon Sep 17 00:00:00 2001 From: santoslgl01-web Date: Sun, 26 Apr 2026 22:43:03 -0300 Subject: [PATCH 3/3] fix: address active filter review feedback --- docs/script.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/script.js b/docs/script.js index c2cf42cc..7c44117a 100644 --- a/docs/script.js +++ b/docs/script.js @@ -1085,15 +1085,15 @@ function getActiveFilterSummaries() { .map(([id, defaultValue]) => { const element = document.getElementById(id); if (!element || element.value === defaultValue) return null; - return `${FILTER_LABELS[id]}: ${getControlDisplayValue(element)}`; + const displayValue = getControlDisplayValue(element); + return displayValue ? `${FILTER_LABELS[id]}: ${displayValue}` : null; }) .filter(Boolean); } -function renderActiveFilterIndicator(container) { +function renderActiveFilterIndicator(container, activeFilters) { if (!container) return; - const activeFilters = getActiveFilterSummaries(); if (!activeFilters.length) { container.style.display = 'none'; container.replaceChildren(); @@ -1124,9 +1124,14 @@ function renderActiveFilterIndicator(container) { } function updateActiveFilterIndicators() { - renderActiveFilterIndicator(document.getElementById('activeFiltersSummary')); + const activeFilters = getActiveFilterSummaries(); + renderActiveFilterIndicator( + document.getElementById('activeFiltersSummary'), + activeFilters, + ); renderActiveFilterIndicator( document.getElementById('activeFiltersSummaryDesktop'), + activeFilters, ); }