From 1468ae78ff9c28f68c9e53b6bcef8d5e98383850 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 3 May 2026 12:47:17 +0800 Subject: [PATCH 01/12] feat(website): show project description as always-visible desc-row on category pages Co-Authored-By: Claude --- uv.lock | 2 +- website/static/main.js | 27 +++++++++++++---- website/static/style.css | 53 +++++++++++++++++++++++++++++++++ website/templates/category.html | 12 ++++++-- 4 files changed, 84 insertions(+), 10 deletions(-) diff --git a/uv.lock b/uv.lock index a097aafb..635a3db0 100644 --- a/uv.lock +++ b/uv.lock @@ -3,7 +3,7 @@ revision = 3 requires-python = ">=3.13" [options] -exclude-newer = "2026-04-30T04:22:17.540198Z" +exclude-newer = "2026-04-30T04:38:39.45925Z" exclude-newer-span = "P3D" [[package]] diff --git a/website/static/main.js b/website/static/main.js index 5da89699..c922964e 100644 --- a/website/static/main.js +++ b/website/static/main.js @@ -113,7 +113,12 @@ document rows.forEach(function (row, i) { row._origIndex = i; - row._expandRow = row.nextElementSibling; + let next = row.nextElementSibling; + if (next && next.classList.contains("desc-row")) { + row._descRow = next; + next = next.nextElementSibling; + } + row._expandRow = next; }); function collapseAll() { @@ -142,9 +147,11 @@ function applyFilters() { if (show && query) { if (!row._searchText) { let text = row.textContent.toLowerCase(); - const next = row.nextElementSibling; - if (next && next.classList.contains("expand-row")) { - text += " " + next.textContent.toLowerCase(); + if (row._descRow) { + text += " " + row._descRow.textContent.toLowerCase(); + } + if (row._expandRow) { + text += " " + row._expandRow.textContent.toLowerCase(); } row._searchText = text; } @@ -152,6 +159,9 @@ function applyFilters() { } if (row.hidden !== !show) row.hidden = !show; + if (row._descRow && row._descRow.hidden !== !show) { + row._descRow.hidden = !show; + } if (show) { visibleCount++; @@ -262,7 +272,8 @@ function sortRows() { const frag = document.createDocumentFragment(); arr.forEach(function (row) { frag.appendChild(row); - frag.appendChild(row._expandRow); + if (row._descRow) frag.appendChild(row._descRow); + if (row._expandRow) frag.appendChild(row._expandRow); }); tbody.appendChild(frag); applyFilters(); @@ -291,7 +302,11 @@ if (tbody) { // Don't toggle if clicking a link or tag button if (e.target.closest("a") || e.target.closest(".tag")) return; - const row = e.target.closest("tr.row"); + let row = e.target.closest("tr.row"); + if (!row) { + const descRow = e.target.closest("tr.desc-row"); + if (descRow) row = descRow.previousElementSibling; + } if (!row) return; const isOpen = row.classList.contains("open"); diff --git a/website/static/style.css b/website/static/style.css index 53604de1..7a8c5fa7 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -788,6 +788,11 @@ kbd { box-shadow: inset 3px 0 0 var(--accent); } +.row:has(+ .desc-row) td { + border-bottom-color: transparent; + padding-bottom: 0.35rem; +} + .row.open td { background: linear-gradient(180deg, var(--row-open-start), var(--row-open-end)); border-bottom-color: transparent; @@ -919,10 +924,58 @@ th[data-sort].sort-asc::after { transform: rotate(90deg); } +.desc-row td { + padding-top: 0; + padding-bottom: 1rem; + border-bottom: 1px solid var(--line); + color: var(--ink-soft); + font-size: var(--text-sm); + line-height: 1.6; + text-wrap: pretty; + overflow-wrap: break-word; + transition: + background-color 180ms ease, + border-color 180ms ease; +} + +.row:not(.open) + .desc-row td { + border-bottom: 1px solid var(--line); +} + +.row + .desc-row { + cursor: pointer; +} + +.row:not(.open):hover td, +.row:not(.open):hover + .desc-row td { + background: var(--row-hover); +} + +.row.open + .desc-row td { + background: linear-gradient(180deg, var(--row-open-start), var(--row-open-end)); + border-bottom-color: transparent; +} + +.desc-text { + max-width: none; +} + +.desc-text a { + color: var(--accent-deep); +} + +.desc-text a:hover { + color: var(--accent); + text-decoration: underline; + text-decoration-color: var(--accent-underline); + text-underline-offset: 0.2em; +} + .expand-row { display: none; } +.row.open + .desc-row + .expand-row, .row.open + .expand-row { display: table-row; } diff --git a/website/templates/category.html b/website/templates/category.html index 799604d8..19d98175 100644 --- a/website/templates/category.html +++ b/website/templates/category.html @@ -204,13 +204,19 @@ + {% if entry.description %} + + + +
{{ entry.description | safe }}
+ + + {% endif %}
- {% if entry.description %} -
{{ entry.description | safe }}
- {% endif %} {% if entry.also_see %} + {% if entry.also_see %}
Also see: {% for see in entry.also_see %} Date: Sun, 3 May 2026 12:53:56 +0800 Subject: [PATCH 02/12] update description for curses --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5e0652f1..dde54a73 100644 --- a/README.md +++ b/README.md @@ -838,7 +838,7 @@ _Libraries for working with graphical user interface applications._ - [nicegui](https://github.com/zauberzeug/nicegui) - An easy-to-use, Python-based UI framework, which shows up in your web browser. - [pywebview](https://github.com/r0x0r/pywebview/) - A lightweight cross-platform native wrapper around a webview component. - Terminal - - [curses](https://docs.python.org/3/library/curses.html) - Built-in wrapper for [ncurses](http://www.gnu.org/software/ncurses/) used to create terminal GUI applications. + - [curses](https://docs.python.org/3/library/curses.html) - (Python standard library) The built-in wrapper for [ncurses](http://www.gnu.org/software/ncurses/) used to create terminal GUI applications. - [urwid](https://github.com/urwid/urwid) - A library for creating terminal GUI applications with strong support for widgets, events, rich colors, etc. - Wrappers - [gooey](https://github.com/chriskiehl/Gooey) - Turn command line programs into a full GUI application with one line. From fc8d1ba35ed5042dae7a30fb51fac9e3a490b065 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 3 May 2026 13:08:27 +0800 Subject: [PATCH 03/12] feat(website): show desc-row on index page when a filter is active On category pages desc-rows are always visible. On the index page they were always hidden. Now they become visible whenever a tag/category filter is applied, giving filtered results the same richness as category pages. Also tightens two related CSS rules: border-bottom suppression only fires when the adjacent desc-row is actually visible, and the expand-row description is hidden while the desc-row is already showing to avoid duplicate text. Co-Authored-By: Claude --- website/static/main.js | 8 ++++++-- website/static/style.css | 6 +++++- website/templates/index.html | 8 ++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/website/static/main.js b/website/static/main.js index c922964e..2a1507ad 100644 --- a/website/static/main.js +++ b/website/static/main.js @@ -132,6 +132,7 @@ function collapseAll() { function applyFilters() { const query = searchInput ? searchInput.value.toLowerCase().trim() : ""; + const descRowsVisible = !isIndexDocument || activeFilter !== null; let visibleCount = 0; collapseAll(); @@ -159,8 +160,11 @@ function applyFilters() { } if (row.hidden !== !show) row.hidden = !show; - if (row._descRow && row._descRow.hidden !== !show) { - row._descRow.hidden = !show; + if (row._descRow) { + const descHidden = !show || !descRowsVisible; + if (row._descRow.hidden !== descHidden) { + row._descRow.hidden = descHidden; + } } if (show) { diff --git a/website/static/style.css b/website/static/style.css index 7a8c5fa7..a547d95b 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -788,7 +788,7 @@ kbd { box-shadow: inset 3px 0 0 var(--accent); } -.row:has(+ .desc-row) td { +.row:has(+ .desc-row:not([hidden])) td { border-bottom-color: transparent; padding-bottom: 0.35rem; } @@ -980,6 +980,10 @@ th[data-sort].sort-asc::after { display: table-row; } +.desc-row:not([hidden]) + .expand-row .expand-desc { + display: none; +} + .expand-row td { padding-top: 0.1rem; padding-bottom: 1.15rem; diff --git a/website/templates/index.html b/website/templates/index.html index 3fa763e6..367bccc2 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -251,6 +251,14 @@ + {% if entry.description %} + + + +
{{ entry.description | safe }}
+ + + {% endif %} From 9de86ea7853d500646a5980ed11dfdd8e41732d8 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 3 May 2026 18:45:09 +0800 Subject: [PATCH 04/12] feat(website): append #library-index to tag links on non-index pages Tag clicks on category/other pages now land with the results section scrolled into view. Co-Authored-By: Claude --- website/static/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/static/main.js b/website/static/main.js index 2a1507ad..d5b337b3 100644 --- a/website/static/main.js +++ b/website/static/main.js @@ -347,7 +347,7 @@ tags.forEach(function (tag) { } applyFilters(); } else if (url) { - window.location.href = url; + window.location.href = url + "#library-index"; } }); }); From f3f92c691a4fb9396dfe43994f5de90638d605b4 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 3 May 2026 18:49:34 +0800 Subject: [PATCH 05/12] feat(website): render subcategory, group, and source tags as anchor elements Convert
+ {% endfor %} {% for cat in entry.categories %} {{ entry.groups[0] }} - + {% endif %} {% if entry.source_type == 'Built-in' %} - + {% endif %} diff --git a/website/templates/index.html b/website/templates/index.html index 367bccc2..c76cd7c7 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -220,9 +220,9 @@ {% for subcat in entry.subcategories %} - + {% endfor %} {% for cat in entry.categories %} {{ cat }} {% endfor %} - + {% if entry.source_type == 'Built-in' %} - + {% endif %} From f57fc44295be602222edee1fd433694cffe34811 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 3 May 2026 18:54:23 +0800 Subject: [PATCH 06/12] style: bump tag font size to var(--text-xs) and codify 12px minimum font-size rule Co-Authored-By: Claude --- DESIGN.md | 1 + website/static/style.css | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index dd35e50a..1548dfd5 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -75,6 +75,7 @@ Layout and sizing: - The impeccable skill reference rule "cap line length at ~65-75ch" does NOT apply here. Ignore it. Readability at wide widths is carried by vertical rhythm, leading, and the modular type scale instead. - If you believe a width cap is actually necessary for some specific element, ask first with a concrete reason before adding it. - Body type floor is 16px (`--text-base: 1rem`). Content-heavy passages may go to 1.125rem. +- Absolute minimum font size is 12px (`0.75rem`) for ANY text, including pills, badges, tags, captions, footnotes. Anything smaller hits Chrome's default minimum-font-size floor and renders inconsistently across browsers and user accessibility settings. Use `var(--text-xs)` (`0.8rem`) as the smallest token. - When in doubt about any type size, pick one step larger than what the impeccable skill's scale references suggest. The user has repeatedly corrected sizes upward (11+ separate requests across 8 sessions). Never reduce an existing size unprompted. Footer, meta rows, expand content, labels, headings all trend too small by default. - Row numbers in the table: left-align, no leading zeros. The user tried zero-padding and rejected it. - Adjacent heading levels differ by at least 0.25rem of rendered size. diff --git a/website/static/style.css b/website/static/style.css index a547d95b..f39ffe8c 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1050,7 +1050,7 @@ th[data-sort].sort-asc::after { background: var(--accent-soft); color: var(--accent-deep); padding: 0.14rem 0.48rem; - font-size: 0.6rem; + font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.02em; cursor: pointer; @@ -1618,7 +1618,7 @@ th[data-sort].sort-asc::after { .tag { padding: 0.38rem 0.65rem; - font-size: 0.65rem; + font-size: var(--text-xs); } .table-wrap { From 138059feeb7f042fa6f84344d22933a1391cd82c Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 3 May 2026 19:05:40 +0800 Subject: [PATCH 07/12] feat(website): add Awesome Python and Sponsorship links to footer Co-Authored-By: Claude --- website/static/style.css | 4 ++-- website/templates/base.html | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/website/static/style.css b/website/static/style.css index f39ffe8c..bbdac357 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1483,8 +1483,8 @@ th[data-sort].sort-asc::after { .footer-left { display: flex; - flex-direction: column; - gap: 0.3rem; + align-items: center; + gap: 0.6rem; } .footer-brand { diff --git a/website/templates/base.html b/website/templates/base.html index 22b56e98..2b219bd4 100644 --- a/website/templates/base.html +++ b/website/templates/base.html @@ -69,7 +69,9 @@