Menu
Navigation

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.

  • layoutWorkspace

    Arrange the viewport, background and screen-space overlays. Add application UI here, such as an inspector or status bar. API ↗

    • backgroundPane background

      Draw dots, lines or another pattern. It sits outside the transformed scene and receives viewport information. API ↗

    • viewportPan and zoom

      Compose scene items and flow-space overlays. Preserve the supplied items order and the default scene's measurement callback. API ↗

      • nodeBoxNode placement

        Position the node body and its attachments. The default measures the body and places boundary handles against its size. API ↗

        • nodeNode body

          Draw a card, table, chart or any widget. Reuse label and place each supplied inline handle once. API ↗

          • nodeLabelNode text

            Replace the label inside a node. The preset supplies editable text; replacing it also replaces that label implementation. API ↗

          • handle(inline)Connection port

            Draw a port using connection state. The engine supplies connection gestures; getHandles declares its geometry and placement. API ↗

        • handle(boundary)Connection port

          Draw a port using connection state. The engine supplies connection gestures; getHandles declares its geometry and placement. API ↗

        • resizeControlResize grips

          Draw a selected node's resize lines and handles. The engine attaches the resize gestures. API ↗

      • edgeBoxEdge composition

        Compose the edge, label, endpoint targets and bend handles. Keep the supplied children to retain their interactions. API ↗

        • edgeConnection stroke

          Draw the supplied path and markers. Use getEdgePath to change routing geometry, including the engine's hit-test path. API ↗

        • edgeLabelConnection label

          Replace an edge's label with text or a richer widget. The engine supplies its anchor and interaction state. API ↗

        • reconnectHandleEndpoint targets

          Draw the grab area at each edge endpoint. The default is invisible but still receives reconnection gestures. API ↗

        • edgeHandleBend handles

          Draw waypoint and midpoint grips. The engine handles dragging, insertion and removal. API ↗

      • guidesAlignment guides

        Draw alignment feedback from the supplied overlay-local lines. Snapping behavior is configured through interaction. API ↗

      • nodesSelectionRectSelected group bounds

        Draw bounds around multiple selected nodes in flow coordinates. The engine attaches group dragging when box selection is enabled. API ↗

      • connectionLineConnection preview

        Draw the temporary line while connecting ports. Use validity state to distinguish accepted and rejected targets. API ↗

    • selectionBoxSelection marquee

      Draw the rectangle while selecting an area. Its bounds are measured in pane pixels. API ↗

    • nodeToolbar(via toolbars)Node actions

      Draw a node's toolbar. The engine positions it beside the node in screen space, keeping its size constant during zoom. API ↗

    • controlsControl layout

      Arrange zoom, fit and lock buttons. Each supplied child already has its action attached. API ↗

      • controlButtonControl appearance

        Draw one button from its kind, hover and disabled state. Standard click behavior is attached by the engine. API ↗

    • minimapMinimap composition

      Arrange the minimap's background, nodes, mask and viewport outline. The engine handles minimap panning. API ↗

      • minimapBackgroundMinimap surface

        Draw the minimap background within the supplied width and height. API ↗

      • minimapNodeMinimap node

        Draw one node using its minimap rectangle and selection state. API ↗

      • minimapMaskOutside the viewport

        Shade the minimap area outside the visible viewport. API ↗

      • minimapViewportVisible area

        Draw the current viewport outline in minimap coordinates. API ↗

    • contextMenuMenu layout

      Arrange the supplied menu item widgets. The engine positions the menu for right-click and long-press. API ↗

      • menuItemMenu appearance

        Draw one command or separator. getContextMenuItems supplies commands; the engine attaches selection and dismissal behavior. 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

  1. 01

    Resolve the preset

    The installed source merges your config with style defaults. Your custom builders replace matching defaults; all other parts remain available.

  2. 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.

  3. 03

    Compose and measure

    Parent builders place the supplied children. The scene measures node bodies and inline ports after layout, then updates connection geometry.

  4. 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 viewport or nodeBox.
  • Start from the copied base/ functions for structural overrides. Return SizedBox.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 changeWhere it belongs
Colors, spacing and default sizesconfig

Tune the installed widgets without replacing their structure.

Node content, labels, ports and edge visualscustom.node, nodeLabel, handle, edge, edgeLabel

Return your own widgets using supplied data and interaction state.

Workspace, control layout and minimapcustom.layout, controls, minimap

Arrange supplied children, preserving their existing behavior.

Connection points and edge routinggetHandles, getEdgePath

Return geometry that the engine uses for connections and hit testing.

Automatic node arrangementlayout

Choose a graph layout algorithm. custom.layout instead arranges the surrounding UI.

Gestures, connection rules and permissionsinteraction, can, nodeOptions

Configure behavior independently from the widgets that display it.

Application commands and reactionsgetContextMenuItems, on, controller

Define 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.