mirror of
https://github.com/github/awesome-copilot.git
synced 2026-07-14 01:51:02 +00:00
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:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user