This example shows how to create custom edge components in Vue Flow. You’ll learn how to add interactive elements to edges, use custom labels, and create different edge types.
Live Demo
View the live demo on vueflow.dev.
Complete Example
EdgesExample.vue
CustomEdge.vue
initial-elements.ts
< script lang = "ts" setup >
import { VueFlow } from '@vue-flow/core'
import { Background } from '@vue-flow/background'
import { Controls } from '@vue-flow/controls'
import { MiniMap } from '@vue-flow/minimap'
import CustomEdge from './CustomEdge.vue'
import CustomEdge2 from './CustomEdge2.vue'
import { initialEdges , initialNodes } from './initial-elements'
</ script >
< template >
< VueFlow : edges = " initialEdges " : nodes = " initialNodes " fit-view-on-init snap-to-grid >
< template # edge-custom = " props " >
< CustomEdge v-bind = " props " />
</ template >
< template # edge-custom2 = " props " >
< CustomEdge2 v-bind = " props " />
</ template >
< MiniMap />
< Controls />
< Background />
</ VueFlow >
</ template >
Key Concepts
Registering Custom Edges
Use the #edge-{type} template slot to register custom edge components:
< VueFlow : edges = " edges " : nodes = " nodes " >
<template #edge-custom="props">
<CustomEdge v-bind="props" />
</template>
</ VueFlow >
The slot name must match the type property of your edge.
Edge Props
Custom edge components receive these props:
interface EdgeProps < T = any > {
id : string
type : string
source : string
target : string
sourceX : number
sourceY : number
targetX : number
targetY : number
sourcePosition : Position
targetPosition : Position
data ?: T
markerStart ?: string
markerEnd ?: string
style ?: CSSProperties
label ?: string | Component
// ... and more
}
Built-in Edge Types
Vue Flow provides several built-in edge types:
Bezier (Default)
Straight
Step
Smooth Step
Smooth curved edge (default type): { id : 'e1' , source : '1' , target : '2' }
// or explicitly
{ id : 'e1' , source : '1' , target : '2' , type : 'default' }
Direct straight line: { id : 'e1' , source : '1' , target : '2' , type : 'straight' }
Step edge with right angles: { id : 'e1' , source : '1' , target : '2' , type : 'step' }
Step edge with rounded corners: { id : 'e1' , source : '1' , target : '2' , type : 'smoothstep' }
Creating Custom Edges
Basic Custom Edge
A custom edge needs to render the path and optionally labels:
< script setup >
import { getBezierPath } from '@vue-flow/core'
const props = defineProps < EdgeProps >()
const path = computed (() => getBezierPath ( props ))
</ script >
< template >
< path
: id = " id "
: style = " style "
class = "vue-flow__edge-path"
: d = " path [ 0 ] "
: marker-end = " markerEnd "
/>
</ template >
Path Helpers
Vue Flow provides helper functions for different path types:
import {
getBezierPath ,
getStraightPath ,
getStepPath ,
getSmoothStepPath
} from '@vue-flow/core'
// Returns [pathString, labelX, labelY, offsetX, offsetY]
const [ path , labelX , labelY ] = getBezierPath ({
sourceX: props . sourceX ,
sourceY: props . sourceY ,
targetX: props . targetX ,
targetY: props . targetY ,
sourcePosition: props . sourcePosition ,
targetPosition: props . targetPosition ,
})
Adding Interactive Elements
Use EdgeLabelRenderer to add interactive elements to edges:
< template >
< path : d = " path [ 0 ] " class = "vue-flow__edge-path" />
< EdgeLabelRenderer >
< div
: style = " {
position: 'absolute' ,
transform: `translate(-50%, -50%) translate( ${ path [ 1 ] } px, ${ path [ 2 ] } px)` ,
pointerEvents: 'all' ,
} "
class = "nodrag nopan"
>
< button @ click = " removeEdges ( id ) " > Delete </ button >
</ div >
</ EdgeLabelRenderer >
</ template >
The nodrag and nopan classes prevent the edge button from triggering drag or pan events.
Edge Styling
Inline Styles
const edges = ref ([
{
id: 'e1' ,
source: '1' ,
target: '2' ,
style: {
stroke: 'red' ,
strokeWidth: 2
}
}
])
Animated Edges
const edges = ref ([
{
id: 'e1' ,
source: '1' ,
target: '2' ,
animated: true
}
])
Edge Labels
Simple Label
Styled Label
Component Label
{
id : 'e1' ,
source : '1' ,
target : '2' ,
label : 'Edge Label'
}
{
id : 'e1' ,
source : '1' ,
target : '2' ,
label : 'Styled Label' ,
labelStyle : { fill : 'red' , fontWeight : 700 },
labelBgStyle : { fill : '#FFCC00' , fillOpacity : 0.7 },
labelBgPadding : [ 8 , 4 ],
labelBgBorderRadius : 4
}
import CustomLabel from './CustomLabel.vue'
{
id : 'e1' ,
source : '1' ,
target : '2' ,
label : h ( CustomLabel , { text: 'Custom' }, {})
}
Markers
Add arrow markers to edges:
import { MarkerType } from '@vue-flow/core'
const edges = ref ([
{
id: 'e1' ,
source: '1' ,
target: '2' ,
markerEnd: {
type: MarkerType . ArrowClosed ,
width: 20 ,
height: 20 ,
color: '#FF0072'
},
markerStart: {
type: MarkerType . Arrow
}
}
])
Available marker types:
MarkerType.Arrow
MarkerType.ArrowClosed
Edge Data
Pass custom data to edges:
const edges = ref ([
{
id: 'e1' ,
source: '1' ,
target: '2' ,
type: 'custom' ,
data: {
text: 'Custom data' ,
onDelete: handleDelete
}
}
])
Access it in your component:
< script setup >
const props = defineProps < EdgeProps <{
text : string
onDelete : () => void
}> > ()
</ script >
< template >
< div > {{ data . text }} </ div >
< button @ click = " data . onDelete " > Delete </ button >
</ template >
TypeScript Support
import type { EdgeProps } from '@vue-flow/core'
interface CustomEdgeData {
label : string
count : number
}
interface CustomEdgeProps extends EdgeProps < CustomEdgeData > {
data : CustomEdgeData
}
const props = defineProps < CustomEdgeProps >()
Best Practices
Always add inheritAttrs: false to custom edge components: export default {
inheritAttrs: false ,
}
Next Steps
Custom Nodes Create custom node components
Validation Validate connections before creation
Edge API Complete edge type reference
Edge Label Renderer EdgeLabelRenderer documentation