docs(quick-260411-1h2): complete rebuild global items page with sticky toolbar plan
This commit is contained in:
@@ -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 `<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
|
||||
Reference in New Issue
Block a user