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.
<script lang="ts">
import {
SvelteFlow,
Background,
type Node,
type Edge,
type NodeEventWithPointer,
} from '@xyflow/svelte';
import ContextMenu from './ContextMenu.svelte';
import { initialNodes, initialEdges } from './nodes-and-edges';
import '@xyflow/svelte/dist/style.css';
let nodes = $state.raw<Node[]>(initialNodes);
let edges = $state.raw<Edge[]>(initialEdges);
let menu: {
id: string;
top?: number;
left?: number;
right?: number;
bottom?: number;
} | null = $state(null);
let clientWidth: number = $state();
let clientHeight: number = $state();
const handleContextMenu: NodeEventWithPointer = ({ 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.
menu = {
id: node.id,
top: event.clientY < clientHeight - 200 ? event.clientY : undefined,
left: event.clientX < clientWidth - 200 ? event.clientX : undefined,
right:
event.clientX >= clientWidth - 200
? clientWidth - event.clientX
: undefined,
bottom:
event.clientY >= clientHeight - 200
? clientHeight - event.clientY
: undefined,
};
};
// Close the context menu if it's open whenever the window is clicked.
function handlePaneClick() {
menu = null;
}
</script>
<div style="height:100vh;" bind:clientWidth bind:clientHeight>
<SvelteFlow
bind:nodes
bind:edges
onnodecontextmenu={handleContextMenu}
onpaneclick={handlePaneClick}
fitView
>
<Background />
{#if menu}
<ContextMenu
onclick={handlePaneClick}
id={menu.id}
top={menu.top}
left={menu.left}
right={menu.right}
bottom={menu.bottom}
/>
{/if}
</SvelteFlow>
</div>