From d64b47b91098febf2b6336d73341e7f50ab312ce Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 3 May 2026 08:26:37 +0800 Subject: [PATCH] feat(website): mirror index layout on category pages Add search input, filter chips, no-results block, and back-to-top button to category/group/subcategory pages. Pass filter_urls_json to all page types so tag-chip navigation works site-wide. Fix JS so filter-clear and no-results-clear redirect to / on non-index pages instead of trying to filter a non-existent local table. Remove the now-redundant .category-results CSS overrides. Co-Authored-By: Claude --- website/build.py | 7 +++- website/static/main.js | 14 +++++-- website/static/style.css | 15 +------ website/templates/category.html | 72 ++++++++++++++++++++++++++++----- website/tests/test_build.py | 2 +- 5 files changed, 80 insertions(+), 30 deletions(-) diff --git a/website/build.py b/website/build.py index 4b65d2bc..8fed7860 100644 --- a/website/build.py +++ b/website/build.py @@ -339,6 +339,8 @@ def build(repo_root: Path) -> None: shutil.rmtree(site_dir) site_dir.mkdir(parents=True) + filter_urls_json = json.dumps(filter_urls, sort_keys=True, ensure_ascii=False).replace(" None: build_date=build_date.strftime("%B %d, %Y"), sponsors=sponsors, category_urls=category_urls, - filter_urls_json=json.dumps(filter_urls, sort_keys=True, ensure_ascii=False).replace(" None: page_kind="category", category_urls=category_urls, current_path=category_path(category), + filter_urls_json=filter_urls_json, ), encoding="utf-8", ) @@ -394,6 +397,7 @@ def build(repo_root: Path) -> None: page_kind="group", category_urls=category_urls, current_path=group_path(group["slug"]), + filter_urls_json=filter_urls_json, ), encoding="utf-8", ) @@ -431,6 +435,7 @@ def build(repo_root: Path) -> None: parent_category=category, category_urls=category_urls, current_path=subcategory_path(category["slug"], sub["slug"]), + filter_urls_json=filter_urls_json, ), encoding="utf-8", ) diff --git a/website/static/main.js b/website/static/main.js index 0cb0e1f6..4da6f669 100644 --- a/website/static/main.js +++ b/website/static/main.js @@ -341,6 +341,10 @@ tags.forEach(function (tag) { if (filterClear) { filterClear.addEventListener("click", function () { + if (!isIndexPage()) { + window.location.href = "/"; + return; + } activeFilter = null; applyFilters(); }); @@ -349,6 +353,10 @@ if (filterClear) { const noResultsClear = document.querySelector(".no-results-clear"); if (noResultsClear) { noResultsClear.addEventListener("click", function () { + if (!isIndexPage()) { + window.location.href = "/"; + return; + } if (searchInput) searchInput.value = ""; activeFilter = null; applyFilters(); @@ -451,10 +459,8 @@ if (backToTop) { ) { activeSort = { col: sort, order: order }; } - if (isIndexPage()) { - const matched = urlToFilter[location.pathname]; - if (matched) activeFilter = matched; - } + const matched = urlToFilter[location.pathname]; + if (matched) activeFilter = matched; if (q || activeFilter || sort) { sortRows(); } diff --git a/website/static/style.css b/website/static/style.css index 6876dc2b..77b58442 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -430,7 +430,7 @@ kbd { .tag:focus-visible, .back-to-top:focus-visible, .no-results-clear:focus-visible, -.category-table a:focus-visible, +.table a:focus-visible, .footer a:focus-visible, .sort-btn:focus-visible { outline: 2px solid var(--accent); @@ -498,19 +498,6 @@ kbd { text-decoration-color: oklch(100% 0 0 / 0.7); } -.category-results { - padding-top: clamp(2.5rem, 5vw, 3.75rem); -} - -.category-results .results-intro { - grid-template-columns: 1fr; - gap: 0.6rem; -} - -.category-results .results-intro .results-note { - justify-self: start; -} - .sponsor-band { padding-block: clamp(2.5rem, 5.5vw, 4rem); background: diff --git a/website/templates/category.html b/website/templates/category.html index a49dde40..96ced7f5 100644 --- a/website/templates/category.html +++ b/website/templates/category.html @@ -38,24 +38,58 @@ {% endblock %} {% block content %} -
+ +
-

Python Projects in {{ category.name }}

+

Search every project in one place

- Sorted by GitHub stars when available. Click any row for details. + Press / to search. Tap a tag to filter. Click any row for + details.

-

{{ category.name }} results

+
+

Search and filter

+
+ + + + + +
+
+ Filtering for + +
+
+ +

Results

- +
@@ -69,7 +103,11 @@ - + @@ -79,7 +117,7 @@ data-tags="{{ entry.categories | join('||') }}{% if entry.subcategories %}||{{ entry.subcategories | map(attribute='value') | join('||') }}{% endif %}||{{ entry.groups | join('||') }}{% if entry.source_type == 'Built-in' %}||Built-in{% endif %}" tabindex="0" aria-expanded="false" - aria-controls="category-expand-{{ loop.index }}" + aria-controls="expand-{{ loop.index }}" > - +
Row number TagsDetails + +
{{ loop.index }} @@ -145,7 +183,7 @@
@@ -188,6 +226,14 @@
+ +
@@ -203,7 +249,13 @@ rel="noopener" >Submit a project - Browse all + Star the repository
diff --git a/website/tests/test_build.py b/website/tests/test_build.py index b482c1a6..57657a66 100644 --- a/website/tests/test_build.py +++ b/website/tests/test_build.py @@ -302,7 +302,7 @@ class TestBuild: assert 'href="https://example.com/w1"' in category_html assert "A widget." in category_html assert 'href="https://github.com/owner/w2"' in category_html - assert '' in category_html + assert '
' in category_html assert "42" in category_html assert "2026-01-01T00:00:00+00:00" in category_html