Reference · UX pattern catalogueSearch, filter & sort patterns

42 patterns in this category — each with its illustration, what it is, and the fields that matter when you build or review one. Part of the UX pattern catalogue; the raw, agent-readable version is ux-pattern-catalogue/filter-search-patterns.json.

Search

sneakers sneakers men sneakers women sneakers sale Popular searches

Search Suggestions filter-search-003

A dropdown of recommended queries or results appears below the search input as users type. Saves time, reduces typos, and reveals available content. Selected 23% of the time on e-commerce sites (NN/G).

Implementation

shadcn: Combobox. Support four types: query completion, popular matches, scoped/category suggestions, and rich suggestions with thumbnails.

Accessibility

role="combobox" with aria-autocomplete="list", aria-expanded, aria-controls, aria-activedescendant. Down Arrow opens/navigates, Escape closes, Enter selects.

247 results for "hooks" React Hooks Guide Learn about useState, useEffect... Custom Hooks Building reusable hooks... Hook Rules Rules of hooks explained...

Search Results Page filter-search-004

A dedicated page displaying items matching a search query with result counts, highlighted snippets, and pagination. Use for any search returning more than a handful of results.

Implementation

shadcn: Card for each result. Show total count prominently. Include breadcrumb-style query echo. Combine with filter sidebar and sort controls.

Accessibility

Announce result count in aria-live="polite" region. Use semantic <ol> for ordered results. Provide skip links to jump past filters to results.

javasrcip Did you mean: javascript Showing results for "javascript"

Fuzzy Matching filter-search-007

Returns results even when the query contains typos, using edit-distance algorithms. Prevents zero-result dead ends from minor spelling errors.

Implementation

Client-side: Fuse.js with configurable threshold. Server-side: Meilisearch/Algolia have built-in typo tolerance. Show "Did you mean X?" or auto-correct with escape hatch.

Accessibility

If auto-correcting, announce the correction in aria-live="polite" so screen reader users know what changed.

Search... Recent Clear react hooks deployment guide api reference

Recent Searches filter-search-008

Shows the user's past search queries when focusing the empty search input. Show 3-5 items on mobile, up to 10 on desktop. Saves time for repeat queries.

Implementation

Store in localStorage or user account. Display in Command dropdown on focus using CommandGroup labeled "Recent". Include clock icon and "Clear history" action.

Accessibility

Label the group with a heading. Each item must be keyboard-navigable. Clear mechanism must be keyboard-accessible.

react + frontend Save Saved Searches Frontend jobs - Remote React Senior - $150k+

Saved Searches filter-search-009

Lets users save a query + filter combination for later reuse, optionally with notifications for new matches. Use for power users with repeated search criteria (job boards, marketplaces).

Implementation

Add "Save search" button near search bar. Store as named entry with serialized query + filter state. Display in DropdownMenu or dedicated panel.

Accessibility

Save button needs accessible label. Saved search list navigable with arrow keys.

All ▾ Search... All | Docs | API | Blog | Community

Search Scoping filter-search-010

Restricts search to a specific section or content type. Always default to "All" — users expect full-site search and may not notice scope restriction (NN/G).

Implementation

shadcn: Select or ToggleGroup adjacent to search input. Default to "All". On results page, clearly state active scope and offer one-click expansion.

Accessibility

Scope selector needs aria-label="Search scope". Active scope must be programmatically associated with search input. Announce scope changes.

Filter

Brand ▾ Price ▾ Size ▾ Color 124 results

Horizontal Filter Bar filter-search-012

A horizontal row of filter controls above the results grid, each opening a dropdown when clicked. Best for interfaces with fewer than 5-7 filter categories.

Implementation

shadcn: Row of Popover triggers showing category name + active count. Inside each, use Checkbox groups or RadioGroup. Add "Apply" button on mobile.

Accessibility

Each trigger includes category name and active count in accessible name (e.g., "Brand, 2 selected"). Popover content is focus-trapped.

Nike ✕ $50+ ✕ In stock ✕ 3 filters active Clear all

Filter Chips filter-search-013

Small removable pill-shaped elements above results showing all active filters. Each chip has an X button to remove that filter. Essential for showing what is currently filtered.

Implementation

shadcn: Badge with close button (X icon) in a horizontal flex-wrap container. Include "Clear all" button at the end.

Accessibility

Each chip needs a button with accessible label like "Remove filter: Brand - Nike". Support keyboard removal with Delete/Backspace. Announce removal via aria-live.

Brand Nike (42) Adidas (38) Puma (21) Reebok (15) Show 8 more

Multi-Select Filters filter-search-014

Filter groups where users select multiple values simultaneously (e.g., multiple brands). The most common filter interaction pattern.

Implementation

shadcn: Checkbox inside AccordionContent or PopoverContent. Show result count next to each option. For 10+ items, truncate with "Show more" link.

Accessibility

role="group" with aria-labelledby pointing to category heading. Space bar toggles checkboxes. Native <input type="checkbox"> preferred.

Price Range $25 to $150

Range Filters filter-search-015

Allows users to define a numeric or date range via slider handles or min/max text fields. Always pair sliders with text inputs for precise entry.

Implementation

shadcn: Slider (dual-thumb) + two Input fields for min/max. Sync bidirectionally. For dates, use DatePicker with range variant.

Accessibility

Slider needs role="slider" with aria-valuemin/max/now and aria-label. Text input fallback is mandatory for keyboard users. Arrow keys adjust by step.

In stock only Free shipping On sale

Toggle Filters filter-search-016

Binary yes/no filters (e.g., "In stock only," "Free shipping"). Use for naturally boolean attributes. Place prominently as high-priority filters.

Implementation

shadcn: Toggle or Switch. Place above results or at the top of the filter sidebar.

Accessibility

role="switch" with aria-checked, or checkbox pattern. Visible label always required. Announce state change.

Category Electronics Subcategory Screen Size ▾

Cascading Filters filter-search-017

Selections in one filter constrain available options in another (e.g., "Electronics" reveals "Screen Size" but not "Fabric Type"). Prevents impossible combinations.

Implementation

Manage dependency graph in state. Update child options on parent change. shadcn: Select or Combobox for dependent dropdowns. Show disabled options with tooltip.

Accessibility

Disabled options need aria-disabled="true" with tooltip explanation. Announce option changes via aria-live when parent filter updates.

Top Rated New Arrivals Budget Picks Quick filter presets

Filter Presets filter-search-018

Pre-configured filter combinations for common user intents (e.g., "Budget picks," "Top rated," "New arrivals"). 20% of top e-commerce sites lack these despite high value (Baymard).

Implementation

shadcn: ToggleGroup or Button row styled as pills. Each preset applies a known set of filters. Allow combining presets with manual filters.

Accessibility

role="radiogroup" if mutually exclusive, role="group" if combinable. Each preset button needs descriptive label.

My Filters ▾ Work Laptop Search Brand: Dell, Price: $800-1200 Budget Monitor Size: 27", Price: <$300

Saved Filters filter-search-019

Lets users save their current filter configuration as a named preset for reuse. Valuable for power users in SaaS dashboards and job boards.

Implementation

Serialize filter state to JSON. Store per-user. shadcn: Dialog for save form, DropdownMenu for load picker.

Accessibility

Save dialog needs proper focus management. Saved filter list must be keyboard-navigable.

Brand Search brands... Nike (42) New Balance (28) North Face (19) Showing 3 of 47 brands matching "n"

Search Within Filters filter-search-020

A text input within a filter group for searching among filter values (e.g., searching within 200 brands). Essential when a filter category has many values.

Implementation

shadcn: Input at top of filter groups with 15+ options. Filter visible options client-side. Combine with truncation (show top 10, "Show all").

Accessibility

Input needs aria-label="Search [category name]". Results in aria-live region or use aria-activedescendant for filtered list.

Sort

247 results Relevance ▾ Relevance Newest Price: Low → High Price: High → Low

Sort Dropdown filter-search-021

A dropdown for choosing sort criterion and direction (e.g., "Price: Low to High"). The most common sort control. Place right-aligned in the results header.

Implementation

shadcn: Select with predefined sort options. Each option includes both criterion and direction. Place next to result count.

Accessibility

aria-label="Sort by". Keyboard: arrow keys to navigate options, Enter to select.

Name Price ▲ Rating Widget A $12.99 4.5 Widget B $24.99 4.8 Widget C $34.99 4.2

Column Sort filter-search-022

Clicking table column headers sorts by that column. Shift+click adds secondary sort. Standard for data tables.

Implementation

shadcn: DataTable (TanStack Table wrapper) with sortable headers. Show sort direction with arrow icons. Support multi-sort via Shift+click.

Accessibility

Headers need aria-sort="ascending", "descending", or "none". Use <button> inside <th>. Announce sort changes.

Default sort by context: Search → Relevance Feed → Newest first Products → Recommended ✗ Avoid alphabetical as default

Default Sort Order filter-search-023

The initial result order before any user interaction. Should match user intent: relevance for search, recency for feeds, popularity for browsing. Avoid alphabetical as default (NN/G).

Implementation

Set "Relevance" for search results, "Newest" for feeds, "Recommended" for product listings. Show active sort in dropdown.

Accessibility

Current sort indicated visually and programmatically via aria-sort or aria-current on active option.

Name unsorted Price ascending Date descending

Sort Direction Indicators filter-search-024

Visual arrows on sortable columns indicating current sort direction and whether a column is sortable at all.

Implementation

Lucide icons: ChevronUp, ChevronDown, ChevronsUpDown for unsorted. Apply to DataTable headers or active sort option.

Accessibility

Use aria-sort on <th> elements. Icons are decorative (aria-hidden="true") since state is conveyed programmatically.

Combined

🔍 Search products... Brand Price Rating 124 results Sort: Relevance

Search + Filter + Sort Layout filter-search-025

The integrated layout combining search input, filter controls, and sort selector above results. The standard pattern for any list/grid with 20+ items.

Implementation

Layout: search (left/top), filters (below or sidebar), sort dropdown (right in header), result count (left in header). On mobile, collapse filters behind button.

Accessibility

Use landmarks: <search>, <aside> for filters, <main> for results. Provide skip links: "Skip to results," "Skip to filters."

site.com/shop?brand=nike&min=50&sort=price Nike ✕ $50+ ✕ ← → Bookmark / Share / Back

URL-Synced Filters filter-search-026

Serialize active query, filters, sort, and pagination into URL params so the view can be bookmarked, shared, or navigated with browser back/forward.

Implementation

useSearchParams (Next.js/React Router) to sync filter state with URL. Use router.replace() not push to avoid history bloat per filter toggle.

Accessibility

Browser back button should undo filter changes. Announce results update from URL-driven state changes.

Size Small 42 Medium 87 Large 31 XL 0

Filter Counts filter-search-027

Numeric counts next to each filter option showing how many results match (e.g., "Nike (42)"). Prevents selecting filters that produce zero results.

Implementation

Render counts in Badge components or parenthetical text. Gray out zero-count options. Update counts dynamically as other filters apply.

Accessibility

Include count in accessible name of each option (e.g., "Nike, 42 results"). Do not rely on color alone for zero-count indication.

Active filters: Nike ✕ $50+ ✕ 4+ stars ✕ Clear all Showing 42 of 1,247 products

Active Filter Summary filter-search-028

A dedicated area displaying all active filters as removable chips with "Clear all." Place between filter controls and results. 32% of sites lack best practices here (Baymard).

Implementation

Flex-wrap container of Badge components with close buttons. Include "Clear all" Button (ghost variant). Show total result count.

Accessibility

Announce removal and "clear all" via aria-live. Each chip removal: aria-label="Remove filter: [value]". Region: aria-label="Active filters".

Brand Nike Adidas Puma Show 80 results

Apply Button with Count filter-search-029

A button showing expected result count (e.g., "Show 247 results") that applies all pending filter selections at once. Recommended for mobile and batch filtering.

Implementation

shadcn: Button with dynamic label. Update count as users toggle options but do not update results until pressed. Dim results while pending.

Accessibility

Button label must programmatically update with count. Announce "Filters applied, showing N results" after activation.

Performance

react ho| r re rea reac react → API keystrokes debounced (300ms) single request

Debounced Search Input filter-search-030

Delays search API calls until the user stops typing (150-300ms), preventing excessive requests per keystroke. Essential for any search-as-you-type implementation.

Implementation

useDebouncedCallback from use-debounce or useCallback + setTimeout. 150ms for fast APIs, 300ms for slower endpoints. Cancel pending on new input.

Accessibility

Provide visual feedback that search is pending (spinner icon) so users know the system is working.

Client-Side All data loaded Filter in browser ✓ <1000 items Server-Side Send params to API Get filtered results ✓ Large datasets Hybrid Server initial + Client refine

Server-Side vs Client-Side Filtering filter-search-031

Client-side filtering works on loaded data (fast, limited size). Server-side sends params to API (handles large datasets). Use client-side for under ~1000 items, server-side for larger.

Implementation

Client-side: TanStack Table built-in filtering. Server-side: filter params as URL query strings, React Query/SWR for caching. Hybrid: server for initial page, client for refinement.

Accessibility

No difference in ARIA patterns. Ensure loading states are announced for server-side filtering.

brand=nike Cached ✓ brand=adidas Stale (30s) brand=puma Fetch...

Filter Result Caching filter-search-032

Cache filter results so revisiting a previous filter combination returns instantly. Reduces server load and improves perceived performance.

Implementation

React Query / TanStack Query with keys from filter state (e.g., ["products", { brand: "nike" }]). Set staleTime 30s-5min. Client-side: useMemo for filtered arrays.

Accessibility

No specific requirements. Fast responses benefit all users including those using assistive technology.

Documents Index react → [1,3] hooks → [1,2] form → [2,3] Pagefind | Lunr | Fuse.js | Meilisearch | Algolia

Search Indexing filter-search-033

Pre-built data structures enabling sub-millisecond full-text search by mapping terms to documents. Essential for performant search.

Implementation

Client-side: Pagefind (static sites, build-time index), Lunr.js, Fuse.js (fuzzy). Server-side: Elasticsearch, Meilisearch, Algolia. Rebuild index on content changes.

Accessibility

No direct ARIA impact. Enables fast search which benefits all users.

A11y

<search> Search... Go Screen readers: "Search landmark" Jump via landmark navigation

Search Landmark filter-search-034

The ARIA search landmark identifies a search region. Screen reader users can jump directly to it via landmark navigation.

Implementation

Wrap search UI in <search> or <form role="search">. Add aria-label if multiple search regions exist on page.

Accessibility

Required by WCAG for discoverability. Multiple search landmarks each need unique aria-label or aria-labelledby.

sneakers aria-live="polite" 247 results found 🔊 "247 results found" Announced after debounce settles

Live Result Count filter-search-035

An aria-live region announcing result counts to screen reader users when search or filter results change. Prevents the silent-update problem.

Implementation

Element with aria-live="polite" containing "47 results found." Update on filter/search/sort changes. Use "assertive" only for zero results.

Accessibility

Do not announce on every keystroke — wait for debounce. Announce zero results assertively, non-zero politely.

Tab Move between groups Space Toggle checkbox ↑ ↓ Navigate within group Enter Apply / activate button

Filter Keyboard Navigation filter-search-036

All filter controls must be keyboard-operable. Tab moves between groups; Space toggles checkboxes; Arrow keys navigate radio groups/sliders; Enter activates buttons.

Implementation

Use native HTML form elements (built-in keyboard support). Logical tab order: search → filters top-to-bottom → sort → results.

Accessibility

WCAG 2.1.1 (Keyboard). Visible focus indicators with 3:1 contrast (WCAG 2.4.7). Never trap focus in filter panels unless modal.

<fieldset> Brand <legend> Nike Adidas Puma SR: "Brand group, Nike checkbox, checked"

Filter Group Labeling filter-search-037

Each filter group must have a programmatic label associating its heading with controls so screen readers announce context.

Implementation

<fieldset> + <legend> for each group, or role="group" with aria-labelledby pointing to heading. Accordion triggers provide labeling automatically.

Accessibility

WCAG 1.3.1 (Info and Relationships). Every checkbox/radio associated with both own label and group label.

Mobile

Filters In stock On sale Show 42 results

Bottom Sheet Filters filter-search-038

A panel sliding up from the bottom containing filter controls. Keeps controls within thumb reach. Include a visible close button — many users don't discover swipe dismissal (NN/G).

Implementation

shadcn: Drawer (Vaul). Include close button (X) plus swipe-to-dismiss. Add "Apply" button with result count at bottom of sheet.

Accessibility

Trap focus when modal. Close button and swipe handle keyboard-accessible. Announce open/close. Return focus to trigger. Min touch target: 48x48px.

Brand ▴ Nike (42) Adidas (38) Price ▾ Rating ▾

Collapsible Filter Panel filter-search-039

Filter categories that collapse/expand individually on mobile to conserve vertical space. Tap a heading to reveal options.

Implementation

shadcn: Accordion (type: "multiple"). Expand 1-2 most important categories by default. "Filter" button in results header scrolls to/reveals panel.

Accessibility

Accordion triggers are buttons with aria-expanded. Content uses aria-hidden when collapsed. Maintain focus on trigger after toggle.

Filters Brand Price Rating Color Nike Adidas Show 42 results

Full-Screen Filter Overlay filter-search-040

A full-screen modal showing all filter categories. Used when filter interface is complex. User applies filters and returns to results.

Implementation

shadcn: Dialog (full-screen) or Drawer (snap to full height). Category nav on left or tabs at top. "Show N results" button at bottom.

Accessibility

Full focus trap. Escape closes. Return focus to trigger. Announce "Filter dialog opened, N categories available."

All Shoes Clothing Acces... ← swipe to see more →

Horizontal Scroll Chips filter-search-041

A horizontally scrollable row of filter chips at the top of mobile results. Each chip toggles a filter value. Best for 5-12 high-priority options.

Implementation

Scrollable container (overflow-x: auto, flex-nowrap) with shadcn Toggle or ToggleGroup. Add gradient scroll indicators on edges.

Accessibility

Container needs role="toolbar" or role="group" with aria-label. Arrow keys navigate chips. Each chip: aria-pressed. Scroll indicators must not obscure text.

Search... Sort & Filter 3

Sort & Filter Button filter-search-042

A single button opening a bottom sheet with both sort and filter controls. Consolidates two entry points for constrained mobile space.

Implementation

shadcn: Button with filter icon + "Sort & Filter" label. Opens Drawer with two sections: "Sort" (RadioGroup) and "Filter" (Accordion + Checkboxes). Badge with active count.

Accessibility

Button label includes count: "Sort and Filter, 3 active." Panel follows modal/drawer accessibility patterns.