Add Tools page search

This commit is contained in:
Tanner
2026-09-26 00:48:55 +00:00
parent 03b124f295
commit 7bac8b4011
2 changed files with 111 additions and 46 deletions
+32
View File
@@ -379,6 +379,38 @@ footer p {
}
}
.tools-search {
margin: 0 0 32px;
}
.tools-search label {
display: block;
margin-bottom: 8px;
font-weight: 700;
}
.tools-search-controls {
display: flex;
gap: 8px;
}
.tools-search input {
min-width: 0;
flex: 1;
padding: 10px 12px;
border: 1px solid #0005;
border-radius: 4px;
font: inherit;
}
.tools-search button {
padding: 10px 16px;
border: 1px solid #0005;
border-radius: 4px;
background: #eee;
font: inherit;
cursor: pointer;
}
.tools-results-count {
font-size: 14px;
font-weight: 400;
}
.tools-toc {
margin: 32px 0;
padding: 16px 20px;
+38 -5
View File
@@ -84,10 +84,19 @@
<h1>Tools</h1>
<div class="entry">
<p>
Browse the tools and equipment available to Protospace members. This catalog follows the
categories and ordering on the <a href="https://wiki.protospace.ca/Tools_we_have" class="external">Protospace Wiki</a>.
Browse the tools and equipment available to Protospace members. This catalog
comes from the <a href="https://wiki.protospace.ca/Tools_we_have" class="external">Protospace Wiki</a>.
</p>
<nav class="tools-toc" aria-label="Tool categories">
<h2>Search</h2>
<div class="tools-search">
<label for="tool-search">Search tools <span id="tool-results-count" class="tools-results-count" hidden> - Results: …</span></label>
<div class="tools-search-controls">
<input id="tool-search" type="search" placeholder="Search by tool name…" autocomplete="off" />
<button id="tool-search-clear" type="button" hidden>Clear</button>
</div>
</div>
<h2 id="tools-categories-heading">Categories</h2>
<nav id="tools-toc" class="tools-toc" aria-label="Tool categories">
<strong>Jump to a category</strong>
<ul id="tools-toc-list"></ul>
</nav>
@@ -104,15 +113,31 @@
.then((tools) => {
const list = document.querySelector("#tools-list");
const toc = document.querySelector("#tools-toc-list");
const searchInput = document.querySelector("#tool-search");
const clearButton = document.querySelector("#tool-search-clear");
const resultsCount = document.querySelector("#tool-results-count");
const categoriesHeading = document.querySelector("#tools-categories-heading");
const tocNav = document.querySelector("#tools-toc");
const normalize = (value) => value.normalize("NFKD").toLowerCase().replace(/[^\p{L}\p{N}]+/gu, "");
const render = () => {
const query = normalize(searchInput.value);
const categories = new Map();
tools.forEach((tool) => {
const matchingTools = tools
.filter((tool) => !query || normalize(tool.name).includes(query));
resultsCount.hidden = !query;
categoriesHeading.hidden = Boolean(query);
tocNav.hidden = Boolean(query);
resultsCount.textContent = ` - Results: ${matchingTools.length}`;
matchingTools
.forEach((tool) => {
if (!categories.has(tool.category)) categories.set(tool.category, []);
categories.get(tool.category).push(tool);
});
list.replaceChildren();
toc.replaceChildren();
clearButton.hidden = !query;
for (const [category, categoryTools] of categories) {
const sectionId = `tools-${category.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")}`;
const sectionId = `tools-${normalize(category)}`;
const tocItem = document.createElement("li");
const tocLink = document.createElement("a");
tocLink.href = `#${sectionId}`;
@@ -148,6 +173,14 @@
}
list.append(grid);
}
};
searchInput.addEventListener("input", render);
clearButton.addEventListener("click", () => {
searchInput.value = "";
searchInput.focus();
render();
});
render();
})
.catch((error) => {
document.querySelector("#tools-list").textContent = error.message;