• Start
    • Branch A
    • Branch B
    • Branch C
  • End
import { Flow } from "@cloudflare/kumo";

/** Flow diagram with parallel branching */
export function FlowParallelDemo() {
  return (
    <Flow>
      <Flow.Node>Start</Flow.Node>
      <Flow.Parallel>
        <Flow.Node>Branch A</Flow.Node>
        <Flow.Node>Branch B</Flow.Node>
        <Flow.Node>Branch C</Flow.Node>
      </Flow.Parallel>
      <Flow.Node>End</Flow.Node>
    </Flow>
  );
}

Installation

Barrel

import { Flow } from "@cloudflare/kumo";

Granular

import { Flow } from "@cloudflare/kumo/components/flow";

Usage

The Flow components work together to create directed flow diagrams. Use Flow as the container, Flow.Node for individual steps, and Flow.Parallel to create branching paths.

import { Flow } from "@cloudflare/kumo";

export default function Example() {
  return (
    <Flow>
      <Flow.Node>Step 1</Flow.Node>
      <Flow.Node>Step 2</Flow.Node>
      <Flow.Node>Step 3</Flow.Node>
    </Flow>
  );
}

Examples

Sequential Flow

A simple linear flow with nodes connected in sequence.

  • Step 1
  • Step 2
  • Step 3
import { Flow } from "@cloudflare/kumo";

/** Basic flow diagram with sequential nodes */
export function FlowBasicDemo() {
  return (
    <Flow>
      <Flow.Node>Step 1</Flow.Node>
      <Flow.Node>Step 2</Flow.Node>
      <Flow.Node>Step 3</Flow.Node>
    </Flow>
  );
}

Parallel Branches

Use Flow.Parallel to create branching paths that run in parallel.

  • Start
    • Branch A
    • Branch B
    • Branch C
  • End
import { Flow } from "@cloudflare/kumo";

/** Flow diagram with parallel branching */
export function FlowParallelDemo() {
  return (
    <Flow>
      <Flow.Node>Start</Flow.Node>
      <Flow.Parallel>
        <Flow.Node>Branch A</Flow.Node>
        <Flow.Node>Branch B</Flow.Node>
        <Flow.Node>Branch C</Flow.Node>
      </Flow.Parallel>
      <Flow.Node>End</Flow.Node>
    </Flow>
  );
}

Custom Node Styling

Use the render prop to completely customize node appearance. The render prop accepts a React element that will be used instead of the default styled node.

  • my-worker
import { Flow } from "@cloudflare/kumo";

/** Flow diagram with custom node styling using render prop */
export function FlowCustomContentDemo() {
  return (
    <Flow>
      <Flow.Node render={<li className="rounded-full size-4 bg-kumo-ring" />} />
      <Flow.Node
        render={
          <li className="bg-kumo-contrast text-kumo-inverse rounded-lg font-medium py-2 px-3">
            my-worker
          </li>
        }
      />
    </Flow>
  );
}

Centered Alignment

Use the align prop to vertically center nodes. This is useful when nodes have different heights.

  • my-worker
  • Taller node
import { Flow } from "@cloudflare/kumo";

/** Flow diagram with vertically centered nodes */
export function FlowCenteredDemo() {
  return (
    <Flow align="center">
      <Flow.Node render={<li className="rounded-full size-4 bg-kumo-ring" />} />
      <Flow.Node>my-worker</Flow.Node>
      <Flow.Node
        render={
          <li className="py-6 px-3 rounded-md shadow bg-kumo-base ring ring-kumo-line">
            Taller node
          </li>
        }
      />
    </Flow>
  );
}

Complex Flow

Combine sequential and parallel nodes to build complex workflows.

    • HTTP Trigger
    • Cron Trigger
  • Process Request
    • Log Analytics
    • Update Cache
    • Send Notification
  • Complete
import { Flow } from "@cloudflare/kumo";

/** Complex flow diagram example */
export function FlowComplexDemo() {
  return (
    <Flow>
      <Flow.Parallel>
        <Flow.Node>HTTP Trigger</Flow.Node>
        <Flow.Node>Cron Trigger</Flow.Node>
      </Flow.Parallel>
      <Flow.Node>Process Request</Flow.Node>
      <Flow.Parallel>
        <Flow.Node>Log Analytics</Flow.Node>
        <Flow.Node>Update Cache</Flow.Node>
        <Flow.Node>Send Notification</Flow.Node>
      </Flow.Parallel>
      <Flow.Node>Complete</Flow.Node>
    </Flow>
  );
}

Custom Anchor Points

By default, connectors attach to the center of each node. Use Flow.Anchor with its render prop to specify custom attachment points. The type prop controls whether the anchor serves as a "start" point (where connectors leave) or "end" point (where connectors arrive).

  • Load balancer
  • my-worker
    Bindings2
    • DATABASE
    • OTHER_SERVICE
import { Flow } from "@cloudflare/kumo";

/** Flow diagram with custom anchor points */
export function FlowAnchorDemo() {
  return (
    <Flow>
      <Flow.Node>Load balancer</Flow.Node>
      <Flow.Node
        render={
          <li className="shadow-none rounded-lg ring ring-kumo-line bg-kumo-overlay">
            <Flow.Anchor
              type="end"
              render={
                <div className="text-kumo-subtle h-10 flex items-center px-2.5">
                  my-worker
                </div>
              }
            />
            <Flow.Anchor
              type="start"
              render={
                <div className="bg-kumo-base rounded ring ring-kumo-line shadow px-2 py-1.5 m-1.5 mt-0">
                  Bindings
                  <span className="text-kumo-subtle w-5 ml-3">2</span>
                </div>
              }
            />
          </li>
        }
      />
      <Flow.Parallel>
        <Flow.Node>DATABASE</Flow.Node>
        <Flow.Node>OTHER_SERVICE</Flow.Node>
      </Flow.Parallel>
    </Flow>
  );
}

Panning Large Diagrams

When a diagram exceeds its container, Flow automatically enables panning. Drag to pan the viewport, or use the scroll wheel. Scrollbars appear on hover to indicate available scroll area.

  • Start
  • Authenticate
  • Validate
  • Transform
  • Process
  • Store
  • Notify
  • Log
  • Complete
  • End
import { Flow } from "@cloudflare/kumo";

/** Large flow diagram demonstrating panning */
export function FlowPanningDemo() {
  return (
    <Flow className="rounded-lg border border-kumo-line">
      <Flow.Node>Start</Flow.Node>
      <Flow.Node>Authenticate</Flow.Node>
      <Flow.Node>Validate</Flow.Node>
      <Flow.Node>Transform</Flow.Node>
      <Flow.Node>Process</Flow.Node>
      <Flow.Node>Store</Flow.Node>
      <Flow.Node>Notify</Flow.Node>
      <Flow.Node>Log</Flow.Node>
      <Flow.Node>Complete</Flow.Node>
      <Flow.Node>End</Flow.Node>
    </Flow>
  );
}

Disabled Nodes

Use the disabled prop on a node to visually indicate it’s inactive. Connectors linking to disabled nodes are rendered with reduced opacity.

  • Request
    • Primary Handler
    • Backup Handler (disabled)
  • Response
import { Flow } from "@cloudflare/kumo";

/** Flow diagram with disabled nodes */
export function FlowDisabledDemo() {
  return (
    <Flow>
      <Flow.Node>Request</Flow.Node>
      <Flow.Parallel>
        <Flow.Node>Primary Handler</Flow.Node>
        <Flow.Node disabled>Backup Handler (disabled)</Flow.Node>
      </Flow.Parallel>
      <Flow.Node>Response</Flow.Node>
    </Flow>
  );
}

Parallel Node Alignment

Use the align prop on Flow.Parallel to control how nodes with different widths are aligned. Use "start" (default) to align left, or "end" to align right.

  • Start
    • Short
    • Medium Length
    • Very Long Node Name
  • End
import { Flow } from "@cloudflare/kumo";

/** Flow diagram with right-aligned parallel nodes */
export function FlowParallelAlignEndDemo() {
  return (
    <Flow>
      <Flow.Node>Start</Flow.Node>
      <Flow.Parallel align="end">
        <Flow.Node>Short</Flow.Node>
        <Flow.Node>Medium Length</Flow.Node>
        <Flow.Node>Very Long Node Name</Flow.Node>
      </Flow.Parallel>
      <Flow.Node>End</Flow.Node>
    </Flow>
  );
}

Known Issue: Sidebar / Layout Shift

Toggling the sidebar shifts the Flow container’s viewport position. Because connector coordinates are computed from stale getBoundingClientRect values stored in state (captured before the layout shift), the connector lines jump out of alignment until the next remeasure is triggered. Scroll the page while the sidebar is open to hit the same bug via the scroll path.

Toggle the sidebar — connectors should stay aligned

Sidebar

Overview
Settings
Logs
Analytics
  • HTTP Request
    • Auth Check
    • Rate Limit
    • Cache Lookup
  • Route Handler
    • Log
    • Respond
import { useState } from "react";
import { Flow } from "@cloudflare/kumo";
import { SidebarSimpleIcon } from "@phosphor-icons/react";

/**
 * Repro: connector lines misalign when a sidebar shifts the layout.
 * Toggle the sidebar to see connectors jump out of place (the bug) or
 * stay aligned (after the fix). Scroll the page while the sidebar is
 * open to trigger the same stale-rect issue.
 */
export function FlowSidebarBugDemo() {
  const [sidebarOpen, setSidebarOpen] = useState(true);

  return (
    <div className="relative overflow-hidden rounded-lg ring ring-kumo-line bg-kumo-base min-h-64 flex flex-col">
      {/* Toolbar */}
      <div className="flex items-center gap-2 border-b border-kumo-line px-3 py-2 shrink-0">
        <button
          type="button"
          onClick={() => setSidebarOpen((v) => !v)}
          className="flex items-center gap-1.5 rounded px-2 py-1 text-xs font-medium text-kumo-default hover:bg-kumo-elevated transition-colors"
        >
          <SidebarSimpleIcon className="size-4" />
          {sidebarOpen ? "Close sidebar" : "Open sidebar"}
        </button>
        <span className="text-xs text-kumo-subtle">
          Toggle the sidebar — connectors should stay aligned
        </span>
      </div>

      {/* Body */}
      <div className="flex flex-1 min-h-0">
        {/* Sidebar */}
        <div
          className="shrink-0 overflow-hidden transition-[width] duration-300 border-r border-kumo-line bg-kumo-elevated"
          style={{ width: sidebarOpen ? 160 : 0 }}
        >
          <div className="w-40 p-3 space-y-1">
            <p className="text-xs font-semibold text-kumo-subtle uppercase tracking-wide mb-2">
              Sidebar
            </p>
            {["Overview", "Settings", "Logs", "Analytics"].map((item) => (
              <div
                key={item}
                className="rounded px-2 py-1 text-sm text-kumo-default hover:bg-kumo-base cursor-default"
              >
                {item}
              </div>
            ))}
          </div>
        </div>

        {/* Main content with Flow — fixed height forces inner scroll */}
        <div className="flex-1 overflow-auto p-4 h-48">
          <Flow>
            <Flow.Node>HTTP Request</Flow.Node>
            <Flow.Parallel>
              <Flow.Node>Auth Check</Flow.Node>
              <Flow.Node>Rate Limit</Flow.Node>
              <Flow.Node>Cache Lookup</Flow.Node>
            </Flow.Parallel>
            <Flow.Node>Route Handler</Flow.Node>
            <Flow.Parallel>
              <Flow.Node>Log</Flow.Node>
              <Flow.Node>Respond</Flow.Node>
            </Flow.Parallel>
          </Flow>
        </div>
      </div>
    </div>
  );
}

Other Examples

Nested Node Lists in Parallel

Use Flow.List inside Flow.Parallel to create parallel branches where each branch contains a sequence of connected nodes.

      • Client Users
      • Engineering Team Access
        • All Authenticated Users
        • Client Users
        • Site Users
      • Contractor Access
  • Destinations
import { Flow } from "@cloudflare/kumo";

/** Flow diagram with parallel branches containing nested node sequences */
export function FlowParallelNestedListDemo() {
  return (
    <Flow>
      <Flow.Parallel>
        <Flow.List>
          <Flow.Node>Client Users</Flow.Node>
          <Flow.Node>Engineering Team Access</Flow.Node>
        </Flow.List>
        <Flow.List>
          <Flow.Parallel>
            <Flow.Node>All Authenticated Users</Flow.Node>
            <Flow.Node>Client Users</Flow.Node>
            <Flow.Node>Site Users</Flow.Node>
          </Flow.Parallel>
          <Flow.Node>Contractor Access</Flow.Node>
        </Flow.List>
      </Flow.Parallel>
      <Flow.Node>Destinations</Flow.Node>
    </Flow>
  );
}

Components

Flow

The root container for flow diagrams. Provides panning and scrolling for large diagrams.

PropTypeDescription
align”start” | “center”

Vertical alignment of nodes. "start" (default) aligns to top, "center" vertically centers nodes.

classNamestringAdditional CSS classes for the container
childrenReactNodeFlow.Node and Flow.Parallel components

Flow.Node

A single node in the flow diagram. Renders as a styled card with automatic connector points. Use the render prop to customize the element.

PropTypeDescription
renderReactElement

Custom element to render instead of the default styled node

disabledboolean

When true, connectors linking to this node are rendered with reduced opacity

childrenReactNodeContent to display inside the node

Flow.Anchor

A component that marks a custom attachment point for connectors within a Flow.Node. Use this to control exactly where connector lines attach instead of the default node center by providing a custom element via the render prop.

PropTypeDescription
type”start” | “end”

Whether this anchor serves as a “start” point (outgoing connectors) or “end” point (incoming connectors). When omitted, serves as both.

renderReactElementCustom element to render for the anchor point
childrenReactNodeContent to render at the anchor point

Flow.Parallel

A container for parallel branches. Child Flow.Node components are displayed in parallel with junction connectors.

PropTypeDescription
align”start” | “end”

Controls horizontal alignment of nodes within the parallel group. "start" (default) aligns left, "end" aligns right.

childrenReactNode

Flow.Node or Flow.List components to display in parallel

Flow.List

A container for a sequence of Flow.Node components with automatic connectors between them. Use inside Flow.Parallel to create branches with multiple sequential steps.

PropTypeDescription
childrenReactNodeFlow.Node components to display in sequence