From 770c5128b77254f41851599c364f67ede17cec4c Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Sat, 11 Apr 2026 01:13:28 +0200 Subject: [PATCH] docs(quick-260411-1h2): complete rebuild global items page with sticky toolbar plan --- .../260411-1h2-SUMMARY.md | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 .planning/quick/260411-1h2-rebuild-global-items-page-with-sticky-se/260411-1h2-SUMMARY.md diff --git a/.planning/quick/260411-1h2-rebuild-global-items-page-with-sticky-se/260411-1h2-SUMMARY.md b/.planning/quick/260411-1h2-rebuild-global-items-page-with-sticky-se/260411-1h2-SUMMARY.md new file mode 100644 index 0000000..9b6c8b1 --- /dev/null +++ b/.planning/quick/260411-1h2-rebuild-global-items-page-with-sticky-se/260411-1h2-SUMMARY.md @@ -0,0 +1,88 @@ +--- +phase: quick +plan: 260411-1h2 +subsystem: client/routes +tags: [global-items, filters, search, ui, sticky-toolbar] +dependency_graph: + requires: [] + provides: [rebuilt-global-items-page] + affects: [src/client/routes/global-items/index.tsx] +tech_stack: + added: [] + patterns: [inline-filter-popovers, click-outside-useref, debounced-search, client-side-range-filter] +key_files: + created: [] + modified: + - src/client/routes/global-items/index.tsx +decisions: + - Inline popovers (not sidebar) for tag/weight/price filters — matches plan spec, avoids layout shift + - click-outside via useRef + mousedown listener (3 refs) — no framer-motion needed + - GlobalItemListRow defined in same file — no new component file needed +metrics: + duration: ~15 minutes + completed: 2026-04-10T23:13:02Z + tasks_completed: 1 + files_modified: 1 +--- + +# Quick 260411-1h2: Rebuild Global Items Page with Sticky Toolbar Summary + +**One-liner:** Rebuilt global items page with sticky two-row toolbar (search + view toggle + inline tag/weight/price filter popovers), grid/list view toggle using GlobalItemCard and Link-based list rows. + +## Tasks Completed + +| Task | Name | Commit | Files | +|------|------|--------|-------| +| 1 | Rebuild global items page with sticky toolbar, filters, and dual view | ee3b6f7 | src/client/routes/global-items/index.tsx | + +## What Was Built + +`src/client/routes/global-items/index.tsx` was completely rewritten from a simple 94-line grid-only page to a 640+ line full-featured catalog browsing page: + +**Sticky toolbar** (`sticky top-14 z-[5]`) with two rows: +- Row 1: Back link to Discover, centered search input with clear (X) button, grid/list view toggle +- Row 2 (conditional): Tags, Weight, Price filter pills — only shown when tags exist or any filter is active + +**Filter popovers:** +- Tags: dropdown listing all tags from `useTags()` — click to toggle, active tags highlighted blue, count badge on pill +- Weight: min/max range sliders (0–5000g, 50g steps) in a compact card popover +- Price: min/max range sliders (0–100000 cents, 500 cent steps) in a compact card popover +- All popovers close on click-outside via `useRef` + `mousedown` event listener +- Only one popover open at a time (opening one closes others) + +**Active filter pills:** +- Selected tag names shown as removable blue pills +- Active weight/price range bounds shown as removable pills +- "Clear all" button clears all filters at once + +**Results area:** +- Grid view: `GlobalItemCard` (existing component, untouched) +- List view: `GlobalItemListRow` (inline component, uses `` for navigation, no Add button) +- Loading: `SkeletonGrid` / `SkeletonList` (6-item animate-pulse layouts) +- Empty: contextual message based on whether query/filters are active + +**Data flow:** +- `searchInput` debounced 300ms to `debouncedQuery` → passed to `useGlobalItems()` +- `selectedTags` passed to `useGlobalItems()` for server-side tag filtering +- Weight/price filters applied client-side via `useMemo` +- Search input pre-filled from `?q=` URL param on mount + +## Deviations from Plan + +None — plan executed exactly as written. + +## Known Stubs + +None — all functionality is wired to real data hooks. + +## Self-Check + +- [x] `src/client/routes/global-items/index.tsx` exists and is 640+ lines +- [x] Commit ee3b6f7 exists +- [x] `bun run lint` passes with no errors +- [x] `createFileRoute("/global-items/")` preserved +- [x] `validateSearch` with `z.object({ q: z.string().optional().catch(undefined) })` preserved +- [x] `CatalogSearchOverlay.tsx` untouched +- [x] `GlobalItemCard.tsx` untouched + +## Self-Check: PASSED