Skip to content

feat: catalog search and filter sheet with URL state (UX-09) - #213

Merged
bri-b-dev merged 1 commit into
mainfrom
b/catalog-v2
Oct 11, 2026
Merged

bri-b-dev merged 1 commit into
mainfrom
b/catalog-v2

Conversation

@bri-b-dev

Copy link
Copy Markdown
Owner

Summary

  • Sticky search + filter sheet: the search field and a "Filter" button (with an active-count badge) stay on top while scrolling. The sheet (dialog, Esc, Tab trap, focus returns to the button) offers category, place, duration (≤10/20/30 min), difficulty (leicht/mittel/schwer), tags (12 most used, all on demand), favorites, never played, below target (disabled with a hint until a handicap is known). Changes apply live; the footer button shows the result count
  • Active filters as removable chips + "Alle zurücksetzen" + "N von 69 Drills" (live region)
  • Filter state in the URL (?q=&cat=&tag=&dur=&diff=&place=&fav=1&new=1&low=1): shareable, replace instead of push (Back leaves the list), other query params are kept, quick successive changes build on each other. Back from a drill restores filter and scroll position (the router waits for the 250 ms page transition before restoring)
  • Search: title, tags, summary and category; every word must match; umlaut tolerant ("fuer", "für", "fur" and "ueben"/"üben" find the same)
  • Cards: inline diagram thumbnail (lazy via IntersectionObserver; inline because the diagrams use the theme variables; ids are made unique per thumbnail since e.g. arrow exists in 40 files), duration, difficulty dots, level stars, tags. Groups by category with sticky headings
  • Empty state: "Keine Drills gefunden" with Filter zurücksetzen
  • The shuffle overlay still starts from the list's category and tag

Bug fix found on the way

<main> had overflow: auto although the window is what scrolls. That made <main> the sticky container, so no sticky bar inside it ever stuck to the window - including the drill head from UX-06 and the session bar. Now overflow: visible (guarded by a test).

Numbers

Start chunk 145.2 KB; the list chunk is 18.4 KB (lazy). Tests 338 -> 372, lint 0 errors. Removed the unused filters/drills.ts.

Test plan

  • npm test, npm run lint, npm run typecheck, npm run build (local)
  • CI
  • Manual (phone): search bar and group headings stick below the app header without overlapping; filter sheet by touch; open a drill and go Back (scroll position + filter); shared URL opens with the filter; thumbnails in light/dark; drill head and session bar now stay visible while scrolling

🤖 Generated with Claude Code

- sticky search (umlaut tolerant, title/tags/summary/category, all words) and a filter bottom sheet
  (category, place, duration, difficulty, tags, favorites, never played, below target)
- active filters as removable chips with reset and a result count
- filter state in the URL (replace, other params kept); back from a drill restores filter and scroll position
- cards with inline diagram thumbnail (lazy, unique svg ids), duration, difficulty and level; groups by
  category with sticky headings; empty state with "Filter zurücksetzen"
- fix: <main> was an overflow container so no sticky bar stuck to the window (also the drill head)
- tests (372)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@bri-b-dev
bri-b-dev merged commit 424c220 into main Oct 11, 2026
1 check passed
@bri-b-dev
bri-b-dev deleted the b/catalog-v2 branch October 11, 2026 08:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant