Skip to Content

Context Menu

The onNodeContextMenu event can be used to show a custom menu when right-clicking a node. This example shows a simple menu with buttons to duplicate or delete the clicked node.

import React, { useCallback, useRef, useState } from 'react'; import { ReactFlow, Background, useNodesState, useEdgesState, addEdge, } from '@xyflow/react'; import '@xyflow/react/dist/style.css'; import { initialNodes, initialEdges } from './initialElements'; import ContextMenu from './ContextMenu'; const Flow = () => { const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); const [menu, setMenu] = useState(null); const ref = useRef(null); const onConnect = useCallback( (params) => setEdges((els) => addEdge(params, els)), [setEdges], ); const onNodeContextMenu = useCallback( (event, node) => { // Prevent native context menu from showing event.preventDefault(); // Calculate position of the context menu. We want to make sure it // doesn't get positioned off-screen. const pane = ref.current.getBoundingClientRect(); setMenu({ id: node.id, top: event.clientY < pane.height - 200 && event.clientY, left: event.clientX < pane.width - 200 && event.clientX, right: event.clientX >= pane.width - 200 && pane.width - event.clientX, bottom: event.clientY >= pane.height - 200 && pane.height - event.clientY, }); }, [setMenu], ); // Close the context menu if it's open whenever the window is clicked. const onPaneClick = useCallback(() => setMenu(null), [setMenu]); return ( <ReactFlow ref={ref} nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} onPaneClick={onPaneClick} onNodeContextMenu={onNodeContextMenu} fitView style={{ backgroundColor: "#F7F9FB" }} > <Background /> {menu && <ContextMenu onClick={onPaneClick} {...menu} />} </ReactFlow> ); }; export default Flow;
Last updated on