feat: add search functionality to workflow node library panel (#2597)

Co-authored-by: Jonathan Dobson <jon.m.dobson@gmail.com>
This commit is contained in:
Prakash Maheshwaran
2025-06-07 21:31:03 -04:00
committed by GitHub
parent 211cdaa94c
commit 2216cb11f7

View File

@@ -1,10 +1,16 @@
import { ScrollArea, ScrollAreaViewport } from "@/components/ui/scroll-area"; import { ScrollArea, ScrollAreaViewport } from "@/components/ui/scroll-area";
import { useWorkflowPanelStore } from "@/store/WorkflowPanelStore"; import { useWorkflowPanelStore } from "@/store/WorkflowPanelStore";
import { Cross2Icon, PlusIcon } from "@radix-ui/react-icons"; import { useState } from "react";
import {
Cross2Icon,
PlusIcon,
MagnifyingGlassIcon,
} from "@radix-ui/react-icons";
import { WorkflowBlockTypes } from "../../types/workflowTypes"; import { WorkflowBlockTypes } from "../../types/workflowTypes";
import { AddNodeProps } from "../FlowRenderer"; import { AddNodeProps } from "../FlowRenderer";
import { WorkflowBlockNode } from "../nodes"; import { WorkflowBlockNode } from "../nodes";
import { WorkflowBlockIcon } from "../nodes/WorkflowBlockIcon"; import { WorkflowBlockIcon } from "../nodes/WorkflowBlockIcon";
import { Input } from "@/components/ui/input";
const enableCodeBlock = const enableCodeBlock =
import.meta.env.VITE_ENABLE_CODE_BLOCK?.toLowerCase() === "true"; import.meta.env.VITE_ENABLE_CODE_BLOCK?.toLowerCase() === "true";
@@ -229,6 +235,26 @@ function WorkflowNodeLibraryPanel({ onNodeClick, first }: Props) {
const closeWorkflowPanel = useWorkflowPanelStore( const closeWorkflowPanel = useWorkflowPanelStore(
(state) => state.closeWorkflowPanel, (state) => state.closeWorkflowPanel,
); );
const [search, setSearch] = useState("");
const filteredItems = nodeLibraryItems.filter((item) => {
if (workflowPanelData?.disableLoop && item.nodeType === "loop") {
return false;
}
if (!enableCodeBlock && item.nodeType === "codeBlock") {
return false;
}
const term = search.toLowerCase();
if (!term) {
return true;
}
return (
item.nodeType.toLowerCase().includes(term) ||
item.title.toLowerCase().includes(term)
);
});
return ( return (
<div className="w-[25rem] rounded-xl border border-slate-700 bg-slate-950 p-5 shadow-xl"> <div className="w-[25rem] rounded-xl border border-slate-700 bg-slate-950 p-5 shadow-xl">
@@ -251,20 +277,24 @@ function WorkflowNodeLibraryPanel({ onNodeClick, first }: Props) {
: "Click on the node type you want to add"} : "Click on the node type you want to add"}
</span> </span>
</header> </header>
<div className="relative">
<div className="absolute left-0 top-0 flex size-9 items-center justify-center">
<MagnifyingGlassIcon className="size-5" />
</div>
<Input
value={search}
onChange={(event) => {
setSearch(event.target.value);
}}
placeholder="Search blocks..."
className="pl-9"
/>
</div>
<ScrollArea> <ScrollArea>
<ScrollAreaViewport className="max-h-[28rem]"> <ScrollAreaViewport className="max-h-[28rem]">
<div className="space-y-2"> <div className="space-y-2">
{nodeLibraryItems.map((item) => { {filteredItems.length > 0 ? (
if ( filteredItems.map((item) => (
workflowPanelData?.disableLoop &&
item.nodeType === "loop"
) {
return null;
}
if (!enableCodeBlock && item.nodeType === "codeBlock") {
return null;
}
return (
<div <div
key={item.nodeType} key={item.nodeType}
className="flex cursor-pointer items-center justify-between rounded-sm bg-slate-elevation4 p-4 hover:bg-slate-elevation5" className="flex cursor-pointer items-center justify-between rounded-sm bg-slate-elevation4 p-4 hover:bg-slate-elevation5"
@@ -296,8 +326,12 @@ function WorkflowNodeLibraryPanel({ onNodeClick, first }: Props) {
</div> </div>
<PlusIcon className="size-6 shrink-0" /> <PlusIcon className="size-6 shrink-0" />
</div> </div>
); ))
})} ) : (
<div className="p-4 text-center text-sm text-slate-400">
No results found
</div>
)}
</div> </div>
</ScrollAreaViewport> </ScrollAreaViewport>
</ScrollArea> </ScrollArea>