Guides
Widget structure
A diagram is a tree of widgets. Replace a leaf to change its appearance, or a parent to rearrange its children.
The widget tree
This is the installed preset's public composition tree. Gesture wrappers and internal render objects are omitted so you can focus on the replaceable parts.
Expand a part to see its role and children. Every name maps to custom.name.
layoutWorkspaceArrange the viewport, background and screen-space overlays. Add application UI here, such as an inspector or status bar. API ↗
backgroundPane backgroundDraw dots, lines or another pattern. It sits outside the transformed scene and receives viewport information. API ↗
viewportPan and zoomCompose scene items and flow-space overlays. Preserve the supplied items order and the default scene's measurement callback. API ↗
nodeBoxNode placementPosition the node body and its attachments. The default measures the body and places boundary handles against its size. API ↗
nodeNode bodyDraw a card, table, chart or any widget. Reuse label and place each supplied inline handle once. API ↗
nodeLabelNode textReplace the label inside a node. The preset supplies editable text; replacing it also replaces that label implementation. API ↗
handle(inline)Connection portDraw a port using connection state. The engine supplies connection gestures; getHandles declares its geometry and placement. API ↗
handle(boundary)Connection portDraw a port using connection state. The engine supplies connection gestures; getHandles declares its geometry and placement. API ↗
resizeControlResize gripsDraw a selected node's resize lines and handles. The engine attaches the resize gestures. API ↗
edgeBoxEdge compositionCompose the edge, label, endpoint targets and bend handles. Keep the supplied children to retain their interactions. API ↗
edgeConnection strokeDraw the supplied path and markers. Use getEdgePath to change routing geometry, including the engine's hit-test path. API ↗
edgeLabelConnection labelReplace an edge's label with text or a richer widget. The engine supplies its anchor and interaction state. API ↗
reconnectHandleEndpoint targetsDraw the grab area at each edge endpoint. The default is invisible but still receives reconnection gestures. API ↗
edgeHandleBend handlesDraw waypoint and midpoint grips. The engine handles dragging, insertion and removal. API ↗
guidesAlignment guidesDraw alignment feedback from the supplied overlay-local lines. Snapping behavior is configured through interaction. API ↗
nodesSelectionRectSelected group boundsDraw bounds around multiple selected nodes in flow coordinates. The engine attaches group dragging when box selection is enabled. API ↗
connectionLineConnection previewDraw the temporary line while connecting ports. Use validity state to distinguish accepted and rejected targets. API ↗
selectionBoxSelection marqueeDraw the rectangle while selecting an area. Its bounds are measured in pane pixels. API ↗
nodeToolbar(via toolbars)Node actionsDraw a node's toolbar. The engine positions it beside the node in screen space, keeping its size constant during zoom. API ↗
minimapMinimap compositionArrange the minimap's background, nodes, mask and viewport outline. The engine handles minimap panning. API ↗
minimapBackgroundMinimap surfaceDraw the minimap background within the supplied width and height. API ↗
minimapNodeMinimap nodeDraw one node using its minimap rectangle and selection state. API ↗
minimapMaskOutside the viewportShade the minimap area outside the visible viewport. API ↗
minimapViewportVisible areaDraw the current viewport outline in minimap coordinates. API ↗
Flow space
Nodes, edges, connection previews and alignment guides move with the viewport. Their coordinates belong to the graph.
Screen space
Controls, toolbars, menus and the selection marquee sit outside the zoom transform. A toolbar follows its node without scaling.
nodeBox and edgeBox repeat for each graph item. The viewport receives an interleaved items list, preserving paint and hit-test order.
How the engine builds it
- 01
Resolve the preset
The installed source merges your config with style defaults. Your custom builders replace matching defaults; all other parts remain available.
- 02
Build children and attach behavior
The engine prepares labels, handles and controls. It wraps interactive visuals with gestures before passing them to their parent builders.
- 03
Compose and measure
Parent builders place the supplied children. The scene measures node bodies and inline ports after layout, then updates connection geometry.
- 04
Update the affected widgets
Controller signals rebuild affected node and edge subtrees. Flitter lays out and paints those widgets using SVG or Canvas.
A builder receives (args, context) and returns a Widget. Args contain data, derived state and sometimes child widgets. Context provides the controller and resolved config.
When a node becomes selected, the engine passes isSelected to its builder. Your widget draws that state; the controller keeps selection, dragging, connections and history consistent.
Builders describe UI. Keep application state in a StatefulWidget, update it with setState(), and use GestureDetector for additional application actions.
Replace a widget, keep its behavior
These examples reuse data from the Quick Start.
Start with a node body
This override changes the body and selection border. Reusing label keeps the preset's label implementation, including its editable text. The engine still attaches the node's standard gestures.
import FlowDiagram from "@/components/diagram/flow-diagram";
import { Border, BoxDecoration, Container, EdgeInsets } from "flitterjs";
FlowDiagram({
data,
custom: {
node: ({ label, isSelected }, { config }) => Container({
width: 180,
padding: EdgeInsets.all(16),
decoration: new BoxDecoration({
color: config.colors.nodeBackground,
border: Border.all({
color: isSelected
? config.colors.nodeSelectedBorder
: config.colors.nodeBorder,
width: 2,
}),
}),
child: label,
}),
},
});For several node designs, dispatch on args.node.type inside custom.node. Each design still returns an ordinary Flitter widget.
Then rearrange a parent
custom.controls receives complete button widgets. Changing their order changes the layout while preserving zoom, fit and lock actions. Use custom.controlButton to change each button's appearance.
import { MainAxisSize, Row } from "flitterjs";
FlowDiagram({
data,
custom: {
controls: ({ zoomIn, zoomOut, fitView, interactive }) => Row({
mainAxisSize: MainAxisSize.min,
children: [zoomOut, fitView, zoomIn, interactive],
}),
},
});When replacing larger branches
- Keep the supplied children you need. Omitting a child also removes its UI and attached interactions.
- Place each inline handle once inside its node. The engine measures its rendered position.
- Preserve scene measurement, attachment placement and item order when replacing
viewportornodeBox. - Start from the copied
base/functions for structural overrides. ReturnSizedBox.shrink()for an empty visual.
See a custom workspace or inline ports inside table rows for complete implementations.
Choose the part you want to change
| What you want to change | Where it belongs |
|---|---|
| Colors, spacing and default sizes | configTune the installed widgets without replacing their structure. |
| Node content, labels, ports and edge visuals | custom.node, nodeLabel, handle, edge, edgeLabelReturn your own widgets using supplied data and interaction state. |
| Workspace, control layout and minimap | custom.layout, controls, minimapArrange supplied children, preserving their existing behavior. |
| Connection points and edge routing | getHandles, getEdgePathReturn geometry that the engine uses for connections and hit testing. |
| Automatic node arrangement | layoutChoose a graph layout algorithm. custom.layout instead arranges the surrounding UI. |
| Gestures, connection rules and permissions | interaction, can, nodeOptionsConfigure behavior independently from the widgets that display it. |
| Application commands and reactions | getContextMenuItems, on, controllerDefine menu actions, react to events, or update the graph programmatically. |
Edit the CLI-installed style/parts/ files to change shared defaults. Pass custom overrides to customize one diagram instance.