Add skeletons to filter panel when search is streaming

This commit is contained in:
bkellam 2025-11-18 12:22:36 -08:00
parent b09def9ddd
commit 74376c022a
3 changed files with 36 additions and 20 deletions

View file

@ -5,6 +5,7 @@ import { compareEntries, Entry } from "./entry";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import Fuse from "fuse.js"; import Fuse from "fuse.js";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
import { Skeleton } from "@/components/ui/skeleton";
interface FilterProps { interface FilterProps {
title: string, title: string,
@ -12,6 +13,7 @@ interface FilterProps {
entries: Entry[], entries: Entry[],
onEntryClicked: (key: string) => void, onEntryClicked: (key: string) => void,
className?: string, className?: string,
isStreaming: boolean,
} }
export const Filter = ({ export const Filter = ({
@ -20,6 +22,7 @@ export const Filter = ({
entries, entries,
onEntryClicked, onEntryClicked,
className, className,
isStreaming,
}: FilterProps) => { }: FilterProps) => {
const [searchFilter, setSearchFilter] = useState<string>(""); const [searchFilter, setSearchFilter] = useState<string>("");
@ -43,27 +46,34 @@ export const Filter = ({
className className
)}> )}>
<h2 className="text-sm font-semibold">{title}</h2> <h2 className="text-sm font-semibold">{title}</h2>
<div className="pr-1"> {(isStreaming && entries.length === 0) ? (
<Input <Skeleton className="h-12 w-full" />
placeholder={searchPlaceholder} ) : (
className="h-8" <>
onChange={(event) => setSearchFilter(event.target.value)} <div className="pr-1">
/> <Input
</div> placeholder={searchPlaceholder}
className="h-8"
<div onChange={(event) => setSearchFilter(event.target.value)}
className="flex flex-col gap-0.5 text-sm overflow-scroll no-scrollbar"
>
{filteredEntries
.sort((entryA, entryB) => compareEntries(entryB, entryA))
.map((entry) => (
<Entry
key={entry.key}
entry={entry}
onClicked={() => onEntryClicked(entry.key)}
/> />
))} </div>
</div>
<div
className="flex flex-col gap-0.5 text-sm overflow-scroll no-scrollbar"
>
{filteredEntries
.sort((entryA, entryB) => compareEntries(entryB, entryA))
.map((entry) => (
<Entry
key={entry.key}
entry={entry}
onClicked={() => onEntryClicked(entry.key)}
/>
))}
</div>
</>
)}
</div> </div>
) )
} }

View file

@ -16,6 +16,7 @@ interface FilePanelProps {
matches: SearchResultFile[]; matches: SearchResultFile[];
repoInfo: Record<number, RepositoryInfo>; repoInfo: Record<number, RepositoryInfo>;
onFilterChange?: () => void; onFilterChange?: () => void;
isStreaming: boolean;
} }
/** /**
@ -33,11 +34,13 @@ interface FilePanelProps {
* @param matches - Array of search result files to filter * @param matches - Array of search result files to filter
* @param repoInfo - Information about repositories including their display names and icons * @param repoInfo - Information about repositories including their display names and icons
* @param onFilterChange - Optional callback that is called whenever a filter is applied or removed * @param onFilterChange - Optional callback that is called whenever a filter is applied or removed
* @param isStreaming - Whether the search is streaming
*/ */
export const FilterPanel = ({ export const FilterPanel = ({
matches, matches,
repoInfo, repoInfo,
onFilterChange, onFilterChange,
isStreaming,
}: FilePanelProps) => { }: FilePanelProps) => {
const router = useRouter(); const router = useRouter();
const searchParams = useSearchParams(); const searchParams = useSearchParams();
@ -155,6 +158,7 @@ export const FilterPanel = ({
} }
}} }}
className="max-h-[50%]" className="max-h-[50%]"
isStreaming={isStreaming}
/> />
<Filter <Filter
title="Filter By Language" title="Filter By Language"
@ -178,6 +182,7 @@ export const FilterPanel = ({
} }
}} }}
className="overflow-auto" className="overflow-auto"
isStreaming={isStreaming}
/> />
</div> </div>
) )

View file

@ -249,6 +249,7 @@ const PanelGroup = ({
<FilterPanel <FilterPanel
matches={fileMatches} matches={fileMatches}
repoInfo={repoInfo} repoInfo={repoInfo}
isStreaming={isStreaming}
onFilterChange={() => { onFilterChange={() => {
searchResultsPanelRef.current?.resetScroll(); searchResultsPanelRef.current?.resetScroll();
}} }}