x-flow-panel
A floating overlay panel anchored to a position within the canvas. Panels stay fixed relative to the container (not the viewport), so they don't move when users pan or zoom. Use them for controls, legends, inspectors, or any overlay UI.
INTERACTIVE
Inspector
Select a node to view details
3 nodes, 2 edges
<div x-data="flowCanvas({
nodes: [
{ id: 'a', position: { x: 0, y: 0 }, data: { label: 'Node A' } },
{ id: 'b', position: { x: 250, y: 0 }, data: { label: 'Node B' } },
{ id: 'c', position: { x: 125, y: 100 }, data: { label: 'Node C' } },
],
edges: [
{ id: 'e1', source: 'a', target: 'c' },
{ id: 'e2', source: 'b', target: 'c' },
],
background: 'dots',
fitViewOnInit: true,
controls: false,
})" class="flow-container" style="height: 250px;">
<div x-flow-panel:top-right.static style="padding: 8px 12px; font-size: 12px;">
<div style="font-weight: 600; margin-bottom: 4px;">Inspector</div>
<div style="opacity: 0.6;">Select a node to view details</div>
</div>
<div x-flow-panel:bottom-left.static style="padding: 6px 10px; font-size: 11px; opacity: 0.6;">
3 nodes, 2 edges
</div>
<div x-flow-viewport>
<template x-for="node in nodes" :key="node.id">
<div x-flow-node="node">
<div x-flow-handle:target.top></div>
<span x-text="node.data.label"></span>
<div x-flow-handle:source.bottom></div>
</div>
</template>
</div>
</div>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
position |
string |
'top-left' |
Anchor position (see below) |
resizable |
bool |
false |
Enable drag-to-resize |
Positions
| Value | Location |
|---|---|
top-left |
Top-left corner |
top-center |
Top center |
top-right |
Top-right corner |
bottom-left |
Bottom-left corner |
bottom-center |
Bottom center |
bottom-right |
Bottom-right corner |
Usage
Place <x-flow-panel> inside <x-flow> (outside the node slot):
<x-flow :nodes="$nodes" :edges="$edges">
<x-slot:node>
<x-flow-handle type="target" position="top" />
<span x-text="node.data.label"></span>
<x-flow-handle type="source" position="bottom" />
</x-slot:node>
<x-flow-panel position="top-right">
<h3 class="text-sm font-semibold">Properties</h3>
<p class="text-xs text-gray-500">Select a node to see its properties.</p>
</x-flow-panel>
</x-flow>
Multiple panels
<x-flow :nodes="$nodes" :edges="$edges">
{{-- ...node slot... --}}
<x-flow-panel position="top-left">
<h2 class="text-sm font-bold">My Workflow</h2>
</x-flow-panel>
<x-flow-panel position="bottom-right">
<span class="text-xs text-gray-400" x-text="nodes.length + ' nodes'"></span>
</x-flow-panel>
</x-flow>
Resizable panel
<x-flow-panel position="top-right" :resizable="true">
<div class="p-3" style="min-width: 200px;">
<h3>Inspector</h3>
<p>Drag corners to resize this panel.</p>
</div>
</x-flow-panel>
Common Patterns
Legend panel
<x-flow-panel position="bottom-left">
<div class="rounded border bg-white p-2 text-xs shadow-sm">
<div class="font-semibold mb-1">Legend</div>
<div class="flex items-center gap-1"><span class="w-3 h-3 rounded bg-green-400"></span> Active</div>
<div class="flex items-center gap-1"><span class="w-3 h-3 rounded bg-yellow-400"></span> Pending</div>
<div class="flex items-center gap-1"><span class="w-3 h-3 rounded bg-red-400"></span> Error</div>
</div>
</x-flow-panel>
Dynamic inspector
<x-flow-panel position="top-right">
<div class="rounded border bg-white p-3 shadow-sm" style="width: 200px;">
<template x-if="selectedNodes.length > 0">
<div>
<h3 class="font-semibold text-sm" x-text="selectedNodes[0].data.label"></h3>
<p class="text-xs text-gray-500 mt-1" x-text="'ID: ' + selectedNodes[0].id"></p>
<p class="text-xs text-gray-500" x-text="'Position: ' + Math.round(selectedNodes[0].position.x) + ', ' + Math.round(selectedNodes[0].position.y)"></p>
</div>
</template>
<template x-if="selectedNodes.length === 0">
<p class="text-xs text-gray-400">Select a node</p>
</template>
</div>
</x-flow-panel>
Directive Mapping
| Blade | Directive |
|---|---|
<x-flow-panel position="top-right" /> |
x-flow-panel:top-right.static |
<x-flow-panel position="bottom-left" :resizable="true" /> |
x-flow-panel:bottom-left |