x-flow
<x-flow> is the root component. Every other WireFlow component (<x-flow-handle>, <x-flow-panel>, <x-flow-toolbar>, etc.) lives inside it. It accepts nodes and edges as PHP arrays and renders an AlpineFlow canvas that can be controlled server-side via the WithWireFlow trait.
<x-flow :nodes="$nodes" :edges="$edges" style="height: 400px;">
<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>
Props
All props are optional unless noted. Props whose default value appears as — are left off the underlying flowCanvas() config and inherit AlpineFlow's own default.
Data
| Prop |
Type |
Default |
Description |
nodes |
array |
[] |
Initial nodes. In sync mode this value is entangled to the Livewire property. |
edges |
array |
[] |
Initial edges. Entangled in sync mode. |
viewport |
array |
['x' => 0, 'y' => 0, 'zoom' => 1] |
Initial pan/zoom. |
Sync mode
| Prop |
Type |
Default |
Description |
sync |
bool |
false |
Two-way bind nodes/edges via $wire.entangle(). Every client-side change flows back to the Livewire property. See State management. |
listen |
bool |
false |
Read-only mode. Canvas is non-interactive; server drives all updates via the WithWireFlow trait. Implies interactive: false. |
Visuals
| Prop |
Type |
Default |
Description |
background |
string |
'dots' |
Background pattern: 'dots', 'lines', 'cross', or 'none'. |
backgroundGap |
int|null |
— |
Pixel spacing between background dots/lines. |
colorMode |
string|null |
— |
'light', 'dark', or 'system'. Overrides the parent theme for this canvas. |
minimap |
bool |
false |
Render the built-in minimap overlay. |
controls |
bool |
false |
Render the built-in zoom/fit/lock toolbar. |
Interaction
| Prop |
Type |
Default |
Description |
interactive |
bool |
true |
Master switch for user input. false disables dragging, connecting, and selection. Automatically false when listen is true. |
pannable |
bool |
true |
Allow panning the viewport. |
zoomable |
bool |
true |
Allow zooming. |
minZoom |
float|null |
— |
Minimum zoom level. |
maxZoom |
float|null |
— |
Maximum zoom level. |
fitView |
bool |
false |
Compute initial zoom to fit all nodes. Static, one-shot. |
fitViewOnInit |
bool |
false |
Run fit-to-view once the canvas initializes. Useful when nodes are loaded asynchronously. |
selectionOnDrag |
bool |
false |
Enable a selection box when dragging on the pane. Pair with 'panOnDrag' => [2] in config to keep middle-click panning. |
snap |
array|false |
false |
Snap-to-grid: [20, 20] for a 20px grid, or false to disable. |
Edges
| Prop |
Type |
Default |
Description |
defaultEdgeType |
string |
'bezier' |
Default edge renderer: 'bezier', 'smoothstep', 'step', 'straight', or any registered custom edge type. |
edgesReconnectable |
bool |
true |
Allow users to drag an edge endpoint to a different handle. |
preventCycles |
bool |
false |
Reject connections that would create a cycle in the graph. |
Layout
| Prop |
Type |
Default |
Description |
autoLayout |
array|null |
— |
Auto-layout config passed through to AlpineFlow's layout engine (e.g. ['direction' => 'TB']). |
computeMode |
string|null |
— |
How node/edge geometry is computed: 'auto' (default), 'lazy', or 'eager'. Advanced — most apps leave this unset. |
Node templates
| Prop |
Type |
Default |
Description |
nodeTypes |
array |
[] |
Map of nodeType => Blade component class used when nodes have a type property. The default slot (<x-slot:node>) is used when a node has no type. |
State
| Prop |
Type |
Default |
Description |
history |
bool |
false |
Enable undo/redo history (drives $this->flowUndo() / $this->flowRedo()). |
Escape hatches
| Prop |
Type |
Default |
Description |
config |
array |
[] |
Pass-through of AlpineFlow config keys not promoted to props. Merged last, so it overrides everything. See Configuration. |
wireIgnore |
bool |
true |
Adds wire:ignore to the canvas <div> so Livewire morphing never clobbers Alpine-managed DOM. Set to false only if you intentionally want Livewire to re-render the entire canvas element. |
containerHeight |
string|int|null |
— |
Canvas height. A number is pixels; a string is any CSS length ('80vh', 'fill' for 100% of the parent). Overrides the --flow-container-height CSS variable. |
fullscreenTarget |
mixed |
— |
Element the fullscreen toggle expands — a CSS selector for the element to take fullscreen instead of the canvas container itself. |
Slots
| Slot |
Purpose |
| Default slot |
Free-form content rendered inside the flow container — typically <x-flow-panel>, <x-flow-toolbar>, <x-flow-context-menu>, or <x-flow-loading>. |
<x-slot:node> |
Template used for nodes that have no type property. Access each node as node inside the slot. |
Named node templates for typed nodes are provided via the nodeTypes prop:
<x-flow
:nodes="$nodes"
:edges="$edges"
:node-types="['decision' => \App\View\Flow\DecisionNode::class]"
>
<x-slot:node>
{{-- default template (nodes without a type) --}}
</x-slot:node>
</x-flow>
Events
Attach any of the following as @event="methodName" to bridge the canvas event to a Livewire method. Only events you wire up are dispatched — omitting the attribute keeps the event client-side only.
See Event Handlers for each event's handler signature and the complete quick-reference table.
| Category |
Events |
| Connections |
connect, connect-start, connect-end, reconnect, reconnect-start, reconnect-end |
| Nodes |
node-click, node-drag-start, node-drag-end, node-resize-start, node-resize-end, node-collapse, node-expand, node-reparent, node-context-menu, nodes-change |
| Edges |
edge-click, edge-context-menu, edges-change |
| Canvas |
pane-click, pane-context-menu, viewport-change |
| Selection |
selection-change, selection-context-menu |
| Rows |
row-select, row-deselect, row-selection-change |
| Other |
drop, init |
<x-flow
:nodes="$nodes"
:edges="$edges"
@connect="onConnect"
@node-drag-end="onNodeDragEnd"
@pane-click="onPaneClick"
/>
For AlpineFlow events not in this list, subscribe inside x-init instead — see Custom event listeners.
JS callbacks
Use WireFlow::js() to pass a client-side JavaScript expression as a config value. The expression is emitted as raw JS, so {{ $user->id }}-style interpolation works.
@use(ArtisanFlow\WireFlow\View\Components\WireFlow)
<x-flow
:nodes="$nodes"
:edges="$edges"
:config="[
'isValidConnection' => WireFlow::js('(conn) => conn.source !== conn.target'),
]"
/>