Add URL-synced listing search (#1217)

* Add URL-synced listing search

Closes #1174

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Aaron Powell
2026-03-30 12:26:37 +11:00
committed by GitHub
parent 1edf5bc29d
commit aa86725613
9 changed files with 401 additions and 17 deletions

View File

@@ -2,7 +2,12 @@
* Tools page functionality
*/
import { FuzzySearch, type SearchableItem } from "../search";
import { fetchData, debounce } from "../utils";
import {
fetchData,
debounce,
getQueryParam,
updateQueryParams,
} from "../utils";
import { renderToolsHtml } from "./tools-render";
export interface Tool extends SearchableItem {
@@ -84,6 +89,13 @@ function renderTools(tools: Tool[], query = ""): void {
});
}
function syncUrlState(searchInput: HTMLInputElement | null): void {
updateQueryParams({
q: searchInput?.value ?? "",
category: currentFilters.categories,
});
}
function setupCopyConfigHandlers(): void {
if (copyHandlersReady) return;
@@ -157,18 +169,33 @@ export async function initToolsPage(): Promise<void> {
)
.join("");
const initialCategory = getQueryParam("category");
if (initialCategory && data.filters.categories.includes(initialCategory)) {
currentFilters.categories = [initialCategory];
categoryFilter.value = initialCategory;
}
categoryFilter.addEventListener("change", () => {
currentFilters.categories = categoryFilter.value
? [categoryFilter.value]
: [];
applyFiltersAndRender();
syncUrlState(searchInput);
});
}
const initialQuery = getQueryParam("q");
if (searchInput) searchInput.value = initialQuery;
applyFiltersAndRender();
// Search input handler
searchInput?.addEventListener(
"input",
debounce(() => applyFiltersAndRender(), 200)
debounce(() => {
applyFiltersAndRender();
syncUrlState(searchInput);
}, 200)
);
// Clear filters
@@ -177,6 +204,7 @@ export async function initToolsPage(): Promise<void> {
if (categoryFilter) categoryFilter.value = "";
if (searchInput) searchInput.value = "";
applyFiltersAndRender();
syncUrlState(searchInput);
});
setupCopyConfigHandlers();