Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed
- Upgraded `brace-expansion` to `^1.1.17`/`^2.1.3`/`^5.0.8`. [#1527](https://github.com/sourcebot-dev/sourcebot/pull/1527)
- The search results panel now distinguishes "the raw search returned no results" from "the active filters excluded everything" when the post-filter list is empty. The latter shows a "No results match the active filters." message with a "Clear filters" button that removes the `repos` and `langs` URL query params. [#1532](https://github.com/sourcebot-dev/sourcebot/pull/1532)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use one sentence for the changelog description.

Line 12 contains two sentences. Join the clauses with a semicolon or rewrite the description as one sentence.

As per coding guidelines, each [Unreleased] entry must describe the change in a single sentence with a link to the PR.

Proposed edit
-- The search results panel now distinguishes "the raw search returned no results" from "the active filters excluded everything" when the post-filter list is empty. The latter shows a "No results match the active filters." message with a "Clear filters" button that removes the "repos" and "langs" URL query params. [`#1532`](https://github.com/sourcebot-dev/sourcebot/pull/1532)
+- The search results panel now distinguishes "the raw search returned no results" from "the active filters excluded everything" when the post-filter list is empty; the active-filter state shows a "No results match the active filters." message with a "Clear filters" button that removes the "repos" and "langs" URL query params. [`#1532`](https://github.com/sourcebot-dev/sourcebot/pull/1532)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` at line 12, Rewrite the changelog entry describing the search
results panel behavior as a single sentence while preserving the distinction
between raw and filtered empty results, the “Clear filters” behavior, and the
existing PR link.

Source: Coding guidelines


## [5.1.5] - 2026-07-31

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { InfoCircledIcon } from "@radix-ui/react-icons";
import { useLocalStorage } from "@uidotdev/usehooks";
import { AlertTriangleIcon, BugIcon, FilterIcon, RefreshCwIcon } from "lucide-react";
import { Session } from "next-auth";
import { useRouter } from "next/navigation";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import { ImperativePanelHandle } from "react-resizable-panels";
Expand All @@ -32,6 +32,8 @@ import { useStreamedSearch } from "../useStreamedSearch";
import { CodePreviewPanel } from "./codePreviewPanel";
import { FilterPanel } from "./filterPanel";
import { useFilteredMatches } from "./filterPanel/useFilterMatches";
import { useGetSelectedFromQuery } from "./filterPanel/useGetSelectedFromQuery";
import { LANGUAGES_QUERY_PARAM, REPOS_QUERY_PARAM } from "./filterPanel/useFilterMatches";
import { SearchResultsPanel, SearchResultsPanelHandle } from "./searchResultsPanel";

interface SearchResultsPageProps {
Expand Down Expand Up @@ -236,6 +238,32 @@ const PanelGroup = ({
const filterPanelRef = useRef<ImperativePanelHandle>(null);
const searchResultsPanelRef = useRef<SearchResultsPanelHandle>(null);
const [selectedMatchIndex, setSelectedMatchIndex] = useState(0);
const pathname = usePathname();
const router = useRouter();
const searchParams = useSearchParams();
const { getSelectedFromQuery } = useGetSelectedFromQuery();

// True iff the user has at least one repo or language filter
// applied. When the post-filter results are empty, this is what
// distinguishes "the query matched nothing" from "the filters
// excluded everything". See issue #1532.
const hasActiveFilters = useMemo(() => {
return getSelectedFromQuery(REPOS_QUERY_PARAM).size > 0
|| getSelectedFromQuery(LANGUAGES_QUERY_PARAM).size > 0;
}, [getSelectedFromQuery, searchParams]);

const onClearFilters = useCallback(() => {
// Preserve every other URL param (the search query, regex
// toggle, etc.) and drop only the repo/language filter params.
// The next render re-derives `filteredFileMatches` from the
// now-empty filter set, so the panel re-renders with all raw
// matches visible.
const next = new URLSearchParams(searchParams.toString());
next.delete(REPOS_QUERY_PARAM);
next.delete(LANGUAGES_QUERY_PARAM);
const qs = next.toString();
router.replace(qs.length > 0 ? `${pathname}?${qs}` : pathname);
}, [pathname, router, searchParams]);

const [isFilterPanelCollapsed, setIsFilterPanelCollapsed] = useLocalStorage('isFilterPanelCollapsed', false);

Expand Down Expand Up @@ -384,6 +412,24 @@ const PanelGroup = ({
<RefreshCwIcon className="h-6 w-6 animate-spin" />
<p className="font-semibold text-center">Searching...</p>
</div>
) : fileMatches.length > 0 && hasActiveFilters ? (
// The raw search returned matches but the
// active repo/language filters excluded all
// of them. The user can't tell the two "no
// results" cases apart without a hint, and
// the filter panel is collapsed by default.
// The "Clear filters" button removes the
// `repos` and `langs` URL params; the next
// render re-derives `filteredFileMatches`
// from the now-empty filter set, so the
// panel re-renders with all raw matches.
// Issue #1532.
<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>
) : (
<div className="flex flex-col items-center justify-center h-full">
<p className="text-sm text-muted-foreground">No results found</p>
Expand Down