HomeWorksExperiments
Writing

© 2025 Guo Ying. Made with midnight builds.

Experiments>

Category & Filter Lab

2025
Category & Filter Lab
SearchFiltersReact

The category page as a single coherent view: scrollable category pills, a dual-handle price slider, star-rating filters, and sort tabs — all wired to one query state that reports how many products match at every step.

Live Demo Source on GitHub
Category
UI Experiment
Theme
Search & filters
Duration
~1 week
Role
Solo — everything
Platform
Web (responsive)
Stack
React · TypeScript · Zustand · Tailwind CSS

The question: can filters feel like one machine instead of a pile of checkboxes?

Every control writes into a single filter object; every read derives the visible list. There is exactly one source of truth, so "clear filters" is one line — setFilters({}) — and the result count is always correct because it is always computed, never cached.

const [filters, setFilters] = useState<Filters>({});
const results = useMemo(
  () => products.filter(matches(filters)),
  [products, filters],
);

What went right: URL sync. ?category=&price_min=&price_max= means a filtered view is shareable and survives a refresh for free.

What went wrong: the price slider. Dual-handle drag with ₫ formatting, debounced writes, and no feedback loop into the input boxes took three rewrites. Sliders are deceptively hard.