Simplify website search and listing controls (#1553)

* Removing search from the home pageThis was a little confusing because there are two searches, but the overall site search is a lot more powerful

* Prefilter website search by resource page

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

* small error handling and formatting

* Simplify website listing controls

Remove per-page text search, trim page-specific controls, and move remaining sort/filter controls into compact flyouts.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Aaron Powell
2026-04-29 16:03:08 +10:00
committed by GitHub
parent 0d7a5ad4c2
commit 76ac13a9b8
29 changed files with 1166 additions and 1331 deletions
+12 -36
View File
@@ -7,10 +7,8 @@ import {
setChoicesValues,
type Choices,
} from '../choices';
import { FuzzySearch, type SearchItem } from '../search';
import {
fetchData,
debounce,
getQueryParam,
getQueryParamValues,
setupDropdownCloseHandlers,
@@ -25,7 +23,7 @@ import {
type RenderableInstruction,
} from './instructions-render';
interface Instruction extends SearchItem, RenderableInstruction {
interface Instruction extends RenderableInstruction {
path: string;
applyTo?: string | string[];
extensions?: string[];
@@ -41,7 +39,6 @@ interface InstructionsData {
const resourceType = 'instruction';
let allItems: Instruction[] = [];
let search = new FuzzySearch<Instruction>();
let extensionSelect: Choices;
let currentFilters = { extensions: [] as string[] };
let currentSort: InstructionSortOption = 'title';
@@ -52,11 +49,8 @@ function sortItems(items: Instruction[]): Instruction[] {
}
function applyFiltersAndRender(): void {
const searchInput = document.getElementById('search-input') as HTMLInputElement;
const countEl = document.getElementById('results-count');
const query = searchInput?.value || '';
let results = query ? search.search(query) : [...allItems];
let results = [...allItems];
if (currentFilters.extensions.length > 0) {
results = results.filter(item => {
@@ -69,22 +63,19 @@ function applyFiltersAndRender(): void {
results = sortItems(results);
renderItems(results, query);
let countText = `${results.length} of ${allItems.length} instructions`;
renderItems(results);
let countText = `${results.length} instruction${results.length === 1 ? '' : 's'}`;
if (currentFilters.extensions.length > 0) {
countText += ` (filtered by ${currentFilters.extensions.length} extension${currentFilters.extensions.length > 1 ? 's' : ''})`;
countText = `${results.length} of ${allItems.length} instructions (filtered by ${currentFilters.extensions.length} extension${currentFilters.extensions.length > 1 ? 's' : ''})`;
}
if (countEl) countEl.textContent = countText;
}
function renderItems(items: Instruction[], query = ''): void {
function renderItems(items: Instruction[]): void {
const list = document.getElementById('resource-list');
if (!list) return;
list.innerHTML = renderInstructionsHtml(items, {
query,
highlightTitle: (title, highlightQuery) => search.highlight(title, highlightQuery),
});
list.innerHTML = renderInstructionsHtml(items);
}
function setupResourceListHandlers(list: HTMLElement | null): void {
@@ -106,9 +97,9 @@ function setupResourceListHandlers(list: HTMLElement | null): void {
resourceListHandlersReady = true;
}
function syncUrlState(searchInput: HTMLInputElement | null): void {
function syncUrlState(): void {
updateQueryParams({
q: searchInput?.value ?? '',
q: '',
extension: currentFilters.extensions,
sort: currentSort === 'title' ? '' : currentSort,
});
@@ -116,7 +107,6 @@ function syncUrlState(searchInput: HTMLInputElement | null): void {
export async function initInstructionsPage(): Promise<void> {
const list = document.getElementById('resource-list');
const searchInput = document.getElementById('search-input') as HTMLInputElement;
const clearFiltersBtn = document.getElementById('clear-filters');
const sortSelect = document.getElementById('sort-select') as HTMLSelectElement;
@@ -129,16 +119,13 @@ export async function initInstructionsPage(): Promise<void> {
}
allItems = data.items;
search.setItems(allItems);
extensionSelect = createChoices('#filter-extension', { placeholderValue: 'All Extensions' });
extensionSelect.setChoices(data.filters.extensions.map(e => ({ value: e, label: e })), 'value', 'label', true);
const initialQuery = getQueryParam('q');
const initialExtensions = getQueryParamValues('extension').filter(extension => data.filters.extensions.includes(extension));
const initialSort = getQueryParam('sort');
if (searchInput) searchInput.value = initialQuery;
if (initialExtensions.length > 0) {
currentFilters.extensions = initialExtensions;
setChoicesValues(extensionSelect, initialExtensions);
@@ -151,33 +138,22 @@ export async function initInstructionsPage(): Promise<void> {
document.getElementById('filter-extension')?.addEventListener('change', () => {
currentFilters.extensions = getChoicesValues(extensionSelect);
applyFiltersAndRender();
syncUrlState(searchInput);
syncUrlState();
});
sortSelect?.addEventListener('change', () => {
currentSort = sortSelect.value as InstructionSortOption;
applyFiltersAndRender();
syncUrlState(searchInput);
syncUrlState();
});
const countEl = document.getElementById('results-count');
if (countEl) {
countEl.textContent = `${allItems.length} of ${allItems.length} instructions`;
}
searchInput?.addEventListener('input', debounce(() => {
applyFiltersAndRender();
syncUrlState(searchInput);
}, 200));
clearFiltersBtn?.addEventListener('click', () => {
currentFilters = { extensions: [] };
currentSort = 'title';
extensionSelect.removeActiveItems();
if (searchInput) searchInput.value = '';
if (sortSelect) sortSelect.value = 'title';
applyFiltersAndRender();
syncUrlState(searchInput);
syncUrlState();
});
applyFiltersAndRender();