docs(quick-260411-1h2): complete rebuild global items page with sticky toolbar plan

This commit is contained in:
2026-04-11 01:13:28 +02:00
parent ee3b6f74e3
commit 770c5128b7

View File

@@ -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 (05000g, 50g steps) in a compact card popover
- Price: min/max range sliders (0100000 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 `<Link>` 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