docs(spec): tag selector search in CatalogSearchOverlay

Captures approved design: in-sidebar typing-to-filter input,
case-insensitive substring match, hidden when tags <= 8,
selected tags filtered out stay active as header pills.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 13:44:15 +02:00
parent 076616cd1b
commit b41aa9301e

View File

@@ -0,0 +1,66 @@
# Tag Selector Search in CatalogSearchOverlay
**Date:** 2026-04-23
**Status:** Approved, ready for implementation
## Problem
The tag filter in the global catalog search overlay (`src/client/components/CatalogSearchOverlay.tsx`) renders every tag as a chip in a narrow sidebar. When the tag taxonomy grows, users must scroll through the full list to find the one they want. There is no typing-to-filter affordance.
## Goal
Allow users to narrow the visible tag list by typing a query, without disrupting selection or the surrounding filter UX.
## Scope
Single-file change to `src/client/components/CatalogSearchOverlay.tsx`. No backend changes. No new dependencies. No shared component extraction.
## Behavior
**Search state**
- Add a `tagSearch: string` local state, defaulting to `""`.
**Input rendering**
- Render a compact text input at the top of the "Tags" section inside the filter sidebar (above the existing tag chip list).
- Style to match the existing minimalist look: similar to the main catalog search input but narrower and with reduced padding so it fits the 224px sidebar.
- Render the input only when `tags.length > 8`. Below that threshold scrolling isn't an issue and the extra chrome is noise.
- Placeholder text: `Filter tags...`.
**Filter logic**
- Compute the visible tag list as: tags whose `name` includes `tagSearch` (case-insensitive substring match).
- A selected tag that does not match the query is hidden from the sidebar list. It remains active and visible as a blue pill in the header row (existing behavior — no change required).
- When the filter produces zero visible tags, render a small muted hint: `No tags match`.
**Reset**
- When the overlay closes, reset `tagSearch` to `""` by extending the existing reset `useEffect` at lines 8498.
## Non-goals
- No fuzzy matching or ranking — plain case-insensitive substring is sufficient.
- No keyboard navigation of the tag list (arrow keys / Enter to toggle). Users click chips.
- No persistence of `tagSearch` across overlay open/close cycles.
- No changes to the active-pill row, active-filter counting, or weight/price range filters.
- No unit tests — pure UI state, covered by manual UAT verification during milestone close-out.
## Acceptance criteria
1. Typing in the tag search input immediately narrows the visible tag chips by case-insensitive substring match on tag name.
2. Tags that are selected but no longer match the query disappear from the sidebar list and remain selected (visible as blue pills in the header).
3. With 8 or fewer tags, the search input is not rendered.
4. With more than 8 tags and a query that matches none of them, a `No tags match` hint is shown.
5. Closing the overlay and reopening it shows an empty tag search input.
6. No regressions to other filter behavior (weight range, price range, active filter pills, clear-all).
## Files touched
- `src/client/components/CatalogSearchOverlay.tsx`
## Out of scope for this spec
- Tag selector in other components (admin items list, etc.).
- Any server-side tag search or query.
- Hierarchy-aware filtering (parent match reveals children, etc.) — tags are consumed flat from `useTags()` in this component.