diff --git a/src/routes/Dashboard/DashboardComponentsV2SourceFilter.tsx b/src/routes/Dashboard/DashboardComponentsV2SourceFilter.tsx
index 7d39a2d84..1ebb65b07 100644
--- a/src/routes/Dashboard/DashboardComponentsV2SourceFilter.tsx
+++ b/src/routes/Dashboard/DashboardComponentsV2SourceFilter.tsx
@@ -1,6 +1,7 @@
import { Button } from "@/components/ui/button";
import { Icon } from "@/components/ui/icon";
import { BlockStack, InlineStack } from "@/components/ui/layout";
+import { QuickTooltip } from "@/components/ui/tooltip";
import { Paragraph, Text } from "@/components/ui/typography";
import { cn } from "@/lib/utils";
import type {
@@ -27,6 +28,16 @@ const SOURCE_FILTER_LABEL_BY_KIND: Record<
user: "User generated",
};
+const SOURCE_FILTER_TOOLTIP_BY_KIND: Record<
+ ComponentSearchSource["kind"],
+ string
+> = {
+ standard: "Standard",
+ published: "Published",
+ registered: "Registered",
+ user: "User",
+};
+
export interface SourceFilterOption {
source: ComponentSearchSource;
count: number;
@@ -79,6 +90,7 @@ interface SourceFilterBarProps {
disabledSourceKeys: string[];
onToggle: (sourceKey: string) => void;
onEnableAll: () => void;
+ display?: "full" | "icons";
}
export const SourceFilterBar = ({
@@ -86,6 +98,7 @@ export const SourceFilterBar = ({
disabledSourceKeys,
onToggle,
onEnableAll,
+ display = "full",
}: SourceFilterBarProps) => {
const disabled = new Set(disabledSourceKeys);
const activeCount = options.filter(
@@ -103,16 +116,20 @@ export const SourceFilterBar = ({
{options.map(({ source, count }) => {
const key = sourceFilterKey(source);
const active = !disabled.has(key);
- return (
+ const label = `${source.label} source (${count} component${count === 1 ? "" : "s"})`;
+ const button = (
);
+
+ if (display === "icons") {
+ return (
+
+ {button}
+
+ );
+ }
+
+ return button;
})}
{activeCount < options.length && (
{isReranking && }
+
void;
clearRerank: () => void;
+ toggleSourceFilter: (sourceKey: string) => void;
+ enableAllSources: () => void;
}
export function registeredSource(
diff --git a/src/routes/v2/pages/Editor/hooks/useComponentSearchV2State.ts b/src/routes/v2/pages/Editor/hooks/useComponentSearchV2State.ts
index b61a63c0c..c18aec362 100644
--- a/src/routes/v2/pages/Editor/hooks/useComponentSearchV2State.ts
+++ b/src/routes/v2/pages/Editor/hooks/useComponentSearchV2State.ts
@@ -17,6 +17,10 @@ import {
LibraryDB,
type StoredLibrary,
} from "@/providers/ComponentLibraryProvider/libraries/storage";
+import {
+ createSourceFilterOptions,
+ filterIndexByDisabledSourceKeys,
+} from "@/routes/Dashboard/DashboardComponentsV2SourceFilter";
import {
buildAiCandidateMatches,
buildLexicalMatches,
@@ -195,10 +199,20 @@ export function useComponentSearchV2State(
}),
);
+ const [disabledSourceKeys, setDisabledSourceKeys] = useState([]);
+ const sourceFilterOptions = createSourceFilterOptions(index);
+ const filteredIndex = filterIndexByDisabledSourceKeys(
+ index,
+ disabledSourceKeys,
+ );
+
const canUseEmbeddingSearch = aiConfig.apiBase.trim().length > 0;
const trimmedQuery = query.trim();
- const lexicalMatches = buildLexicalMatches(index, trimmedQuery);
- const aiCandidateMatches = buildAiCandidateMatches(index, trimmedQuery);
+ const lexicalMatches = buildLexicalMatches(filteredIndex, trimmedQuery);
+ const aiCandidateMatches = buildAiCandidateMatches(
+ filteredIndex,
+ trimmedQuery,
+ );
const {
mutate,
reset: resetRerank,
@@ -225,7 +239,7 @@ export function useComponentSearchV2State(
setRerankedFor(null);
setRerankBaseMatches([]);
embeddingAbortControllerRef.current?.abort();
- }, [query, resetRerank]);
+ }, [query, disabledSourceKeys, resetRerank]);
useEffect(() => {
return () => embeddingAbortControllerRef.current?.abort();
@@ -297,7 +311,7 @@ export function useComponentSearchV2State(
const effectiveLimit = limit || LEXICAL_RESULT_LIMIT;
const embeddingMatches = canUseEmbeddings
? await buildEmbeddingMatches({
- sourceIndex: index,
+ sourceIndex: filteredIndex,
limit: effectiveLimit,
})
: [];
@@ -335,6 +349,16 @@ export function useComponentSearchV2State(
});
};
+ const toggleSourceFilter = (sourceKey: string) => {
+ setDisabledSourceKeys((current) =>
+ current.includes(sourceKey)
+ ? current.filter((key) => key !== sourceKey)
+ : [...current, sourceKey],
+ );
+ };
+
+ const enableAllSources = () => setDisabledSourceKeys([]);
+
const rerankMatchByDigest = buildRerankMatchByDigest(
rerankData,
isRerankActive,
@@ -347,11 +371,18 @@ export function useComponentSearchV2State(
return {
results,
- browseFolders: buildResultFolders({ results, standardLibrary }),
- searchSuggestions: buildComponentSearchSuggestions(index, {
+ browseFolders: buildResultFolders({
+ results,
+ standardLibrary: disabledSourceKeys.includes("standard")
+ ? undefined
+ : standardLibrary,
+ }),
+ searchSuggestions: buildComponentSearchSuggestions(filteredIndex, {
includeSources: false,
query: trimmedQuery,
}),
+ sourceFilterOptions,
+ disabledSourceKeys,
isLoading:
isLoadingStandardLibrary ||
isLoadingUserComponents ||
@@ -367,5 +398,7 @@ export function useComponentSearchV2State(
isRerankActive,
rerank,
clearRerank,
+ toggleSourceFilter,
+ enableAllSources,
};
}