Add a RadialMenu component (#4096)

This commit is contained in:
Jonathan Dobson
2025-11-25 14:35:57 -05:00
committed by GitHub
parent 285694cefe
commit 0a12f4dfb8
3 changed files with 359 additions and 38 deletions

View File

@@ -1,6 +1,4 @@
import { Button } from "@/components/ui/button";
import { useWorkflowPanelStore } from "@/store/WorkflowPanelStore";
import { PlusIcon } from "@radix-ui/react-icons";
import { SquareIcon, PlusIcon } from "@radix-ui/react-icons";
import {
BaseEdge,
EdgeLabelRenderer,
@@ -8,6 +6,13 @@ import {
getBezierPath,
useNodes,
} from "@xyflow/react";
import { Button } from "@/components/ui/button";
import { RadialMenu } from "@/components/RadialMenu";
import { useIsSkyvernUser } from "@/hooks/useIsSkyvernUser";
import { useWorkflowPanelStore } from "@/store/WorkflowPanelStore";
import { useDebugStore } from "@/store/useDebugStore";
import { REACT_FLOW_EDGE_Z_INDEX } from "../constants";
function EdgeWithAddButton({
@@ -22,6 +27,8 @@ function EdgeWithAddButton({
style = {},
markerEnd,
}: EdgeProps) {
const debugStore = useDebugStore();
const isSkyvernUser = useIsSkyvernUser();
const nodes = useNodes();
const [edgePath, labelX, labelY] = getBezierPath({
sourceX,
@@ -36,6 +43,28 @@ function EdgeWithAddButton({
);
const sourceNode = nodes.find((node) => node.id === source);
const onAdd = () => {
setWorkflowPanelState({
active: true,
content: "nodeLibrary",
data: {
previous: source,
next: target,
parent: sourceNode?.parentId,
},
});
};
const adder = (
<Button
size="icon"
className="h-4 w-4 rounded-full transition-all hover:scale-150"
onClick={() => onAdd()}
>
<PlusIcon />
</Button>
);
return (
<>
<BaseEdge path={edgePath} markerEnd={markerEnd} style={style} />
@@ -52,23 +81,38 @@ function EdgeWithAddButton({
}}
className="nodrag nopan"
>
<Button
size="icon"
className="h-4 w-4 rounded-full transition-all hover:scale-150"
onClick={() => {
setWorkflowPanelState({
active: true,
content: "nodeLibrary",
data: {
previous: source,
next: target,
parent: sourceNode?.parentId,
{isSkyvernUser && debugStore.isDebugMode ? (
<RadialMenu
items={[
{
id: "1",
icon: <PlusIcon className="h-3 w-3" />,
text: "Add Block",
onClick: () => {
onAdd();
},
},
});
}}
>
<PlusIcon />
</Button>
{
id: "2",
icon: <SquareIcon className="h-3 w-3" />,
enabled: false,
text: "Record Browser",
onClick: () => {
console.log("Record");
},
},
]}
buttonSize="25px"
radius="50px"
startAt={72.5}
gap={35}
rotateText={true}
>
{adder}
</RadialMenu>
) : (
adder
)}
</div>
</EdgeLabelRenderer>
</>

View File

@@ -1,14 +1,46 @@
import { SquareIcon, PlusIcon } from "@radix-ui/react-icons";
import { Handle, NodeProps, Position, useEdges } from "@xyflow/react";
import type { NodeAdderNode } from "./types";
import { PlusIcon } from "@radix-ui/react-icons";
import { RadialMenu } from "@/components/RadialMenu";
import { useIsSkyvernUser } from "@/hooks/useIsSkyvernUser";
import { useDebugStore } from "@/store/useDebugStore";
import { useWorkflowPanelStore } from "@/store/WorkflowPanelStore";
import type { NodeAdderNode } from "./types";
function NodeAdderNode({ id, parentId }: NodeProps<NodeAdderNode>) {
const debugStore = useDebugStore();
const isSkyvernUser = useIsSkyvernUser();
const edges = useEdges();
const setWorkflowPanelState = useWorkflowPanelStore(
(state) => state.setWorkflowPanelState,
);
const onAdd = () => {
const previous = edges.find((edge) => edge.target === id)?.source;
setWorkflowPanelState({
active: true,
content: "nodeLibrary",
data: {
previous: previous ?? null,
next: id,
parent: parentId,
connectingEdgeType: "default",
},
});
};
const adder = (
<div
className="rounded-full bg-slate-50 p-2"
onClick={() => {
onAdd();
}}
>
<PlusIcon className="h-12 w-12 text-slate-950" />
</div>
);
return (
<div>
<Handle
@@ -23,24 +55,36 @@ function NodeAdderNode({ id, parentId }: NodeProps<NodeAdderNode>) {
id="b"
className="opacity-0"
/>
<div
className="rounded-full bg-slate-50 p-2"
onClick={() => {
const previous = edges.find((edge) => edge.target === id)?.source;
setWorkflowPanelState({
active: true,
content: "nodeLibrary",
data: {
previous: previous ?? null,
next: id,
parent: parentId,
connectingEdgeType: "default",
{isSkyvernUser && debugStore.isDebugMode ? (
<RadialMenu
items={[
{
id: "1",
icon: <PlusIcon />,
text: "Add Block",
onClick: () => {
onAdd();
},
},
});
}}
>
<PlusIcon className="h-12 w-12 text-slate-950" />
</div>
{
id: "2",
icon: <SquareIcon />,
enabled: false,
text: "Record Browser",
onClick: () => {
console.log("Record");
},
},
]}
radius="80px"
startAt={90}
rotateText={true}
>
{adder}
</RadialMenu>
) : (
adder
)}
</div>
);
}