Skip to content

[UX] Search results 'No results found' message should distinguish 'no raw results' from 'filters excluded all results' with a clear-filters action #1532

Description

@Harsh23Kashyap

[UX] Search results "No results found" message should distinguish "no raw results" from "filters excluded all results" with a clear-filters action

Problem

When the user runs a search that returns results, then applies a repo or language filter in the side panel that excludes all matches, the results panel shows a bare "No results found" with no indication that the filters are the cause. The user can see the same message whether (a) the query genuinely matched nothing or (b) the query matched files but the active filters are excluding them. There's no quick way to recover from case (b) without remembering which filters are active and backtracking to the filter panel.

Background

packages/web/src/app/(app)/search/components/searchResultsPage.tsx:382-391:

{filteredFileMatches.length > 0 ? (
    <SearchResultsPanel ... />
) : isStreaming ? (
    <div>Searching...</div>
) : (
    <div className="flex flex-col items-center justify-center h-full">
        <p className="text-sm text-muted-foreground">No results found</p>
    </div>
)}

filteredFileMatches is the post-filter list (derived from fileMatches via useFilteredMatches, which reads repos and langs URL query params). fileMatches is the raw search result. The current code collapses both cases into the same message because the page doesn't know whether the empty filteredFileMatches came from a query that matched nothing or from filters that excluded everything.

A separate, distinct message at searchResultsPage.tsx:354 ("No results") fires when the raw search returned 0 files. So we have two "empty" states with two messages, but the post-filter empty state doesn't tell the user that the filters are the culprit.

Current behavior

A user runs repo:github file:.ts$ (returns 5 files), then opens the filter panel and selects only the python language. The result panel goes blank with "No results found". The user wonders if the query is broken. They have to find the filter panel and clear the language filter manually. The filter panel is collapsed by default (controlled by filterPanelRef.current?.collapse()), so this can be a long round-trip.

Expected behavior

When the raw search returned matches but the filters excluded all of them:

  • The empty-state message says "No results match the active filters" (or similar) instead of "No results found".
  • A "Clear filters" button is rendered next to the message. Clicking it removes the repos and langs URL query params and re-runs the search with all results visible.

When the raw search returned 0 files (the existing "No results" case), the message is unchanged — no filter-clearing affordance, since the filters couldn't have caused the empty result.

Proposed solution

  1. In searchResultsPage.tsx, derive hasActiveFilters from the repos and langs URL query params (reuse useGetSelectedFromQuery from the filter panel; it's already wired up). When fileMatches.length > 0 AND filteredFileMatches.length === 0 AND hasActiveFilters, render a different empty state:
<div className="flex flex-col items-center justify-center h-full gap-3">
    <p className="text-sm text-muted-foreground">No results match the active filters.</p>
    <Button variant="outline" size="sm" onClick={onClearFilters}>
        Clear filters
    </Button>
</div>
  1. onClearFilters removes repos and langs from the URL via router.replace(...) (the page already uses useRouter for the "load more" URL update). No re-fetch needed; React Query re-derives filteredFileMatches from the now-empty filter set.

  2. The header bar's "No results" message at line 354 is unchanged — that case means the search itself returned nothing, and filters couldn't have caused it.

Alternatives considered

  • Auto-clear filters when the user clicks "Clear filters" in the filter panel itself. Rejected: the filter panel already has a "clear" affordance per checkbox, but there's no single "clear all" button and no "no results match your filters" signal anywhere. The empty-state is the natural place to surface the "this is filterable" hint.
  • Make the filter panel auto-expand when the user lands on a no-results-while-filtered state. Useful but bigger change. The empty-state button is the smaller fix.
  • Show a tooltip on the "No results found" text that explains filters are active. Tooltips on empty states are easy to miss; a button is actionable.

Scope

  • 1 file modified (searchResultsPage.tsx).
  • 1 new component or inline JSX for the empty state.
  • 1 new test (or extend an existing one).
  • No API, no schema, no migration.

Acceptance criteria

  • When the raw search returns matches but the filters exclude all of them, the results panel shows "No results match the active filters." with a "Clear filters" button.
  • Clicking "Clear filters" removes the repos and langs URL query params and the panel re-renders with all raw matches visible.
  • When the raw search returns 0 files, the existing "No results" message is shown — no filter-clearing affordance, since filters couldn't have caused the empty result.
  • The "Clear filters" button is only rendered when at least one filter is active.
  • No new TypeScript errors; existing tests still pass; new test covers the new branch.

Backward compatibility

Pure UI change. No API, no schema, no behavior change for users who don't apply filters.

Risks

Minimal. The "Clear filters" button just removes URL query params — a well-trodden path in this codebase (the "load more" button on the same page already does similar URL manipulation).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions