diff --git a/web/src/pages/ExplorePage.svelte b/web/src/pages/ExplorePage.svelte index b6ecfcb..80d3e61 100644 --- a/web/src/pages/ExplorePage.svelte +++ b/web/src/pages/ExplorePage.svelte @@ -304,7 +304,13 @@ scheduleDraw(); } + // Two distinct highlight modes: typing filters icons by metadata + // substring; clicking a cluster selects exactly its members. Each + // activation clears the other so the count always has one meaning. + let activeCluster: string | null = $state(null); + function handleSearch() { + activeCluster = null; const q = searchInput.trim().toLowerCase(); if (!q) { searchHighlight = new Set(); draw(); return; } const hits = new Set(); @@ -320,6 +326,23 @@ draw(); } + function toggleCluster(theme: string) { + if (activeCluster === theme) { clearFilter(); return; } + activeCluster = theme; + searchInput = ""; + searchHighlight = new Set( + manifest.icons.filter((i) => i.cluster === theme).map((i) => i.name), + ); + draw(); + } + + function clearFilter() { + activeCluster = null; + searchInput = ""; + searchHighlight = new Set(); + draw(); + } + let searchTimeout: ReturnType | null = null; function handleSearchInput() { if (searchTimeout) clearTimeout(searchTimeout); @@ -373,11 +396,16 @@ type="text" bind:value={searchInput} oninput={handleSearchInput} - placeholder="Filter clusters..." + placeholder="Filter icons..." /> {#if searchHighlight.size > 0} {searchHighlight.size} {/if} + {#if searchInput || activeCluster} + + {/if}
{clusters.length} clusters
@@ -409,7 +437,8 @@ {#each clusters as cl}