Drag and Drop
This example shows how to implement a sidebar with a drag and drop functionality using the native drag and drop events.
<script lang="ts">
import {
SvelteFlow,
Controls,
Background,
BackgroundVariant,
MiniMap,
useSvelteFlow,
type Node,
} from '@xyflow/svelte';
import { useDnD } from './DnDProvider.svelte';
import Sidebar from './Sidebar.svelte';
import '@xyflow/svelte/dist/style.css';
let nodes = $state.raw([
{
id: '1',
type: 'input',
data: { label: 'Input Node' },
position: { x: 150, y: 5 },
},
{
id: '2',
type: 'default',
data: { label: 'Default Node' },
position: { x: 0, y: 150 },
},
{
id: '3',
type: 'output',
data: { label: 'Output Node' },
position: { x: 300, y: 150 },
},
]);
let edges = $state.raw([
{
id: '1-2',
type: 'default',
source: '1',
target: '2',
},
{
id: '1-3',
type: 'smoothstep',
source: '1',
target: '3',
},
]);
const { screenToFlowPosition } = $derived(useSvelteFlow());
const type = useDnD();
const onDragOver = (event: DragEvent) => {
event.preventDefault();
if (event.dataTransfer) {
event.dataTransfer.dropEffect = 'move';
}
};
const onDrop = (event: DragEvent) => {
event.preventDefault();
if (!type.current) {
return;
}
const position = screenToFlowPosition({
x: event.clientX,
y: event.clientY,
});
const newNode = {
id: `${Math.random()}`,
type: type.current,
position,
data: { label: `${type.current} node` },
origin: [0.5, 0.0],
} satisfies Node;
nodes = [...nodes, newNode];
};
</script>
<main>
<SvelteFlow
bind:nodes
bind:edges
fitView
ondragover={onDragOver}
ondrop={onDrop}
>
<Controls />
<Background variant={BackgroundVariant.Dots} />
<MiniMap />
</SvelteFlow>
<Sidebar />
</main>
<style>
main {
height: 100vh;
display: flex;
flex-direction: column-reverse;
}
</style>