Skip to main content
Gremorie

Canvas

ReactFlow surface for visual workflows and agent graphs. Pre-configured for pan-on-scroll, drag selection and Backspace / Delete deletion.

Overview

Canvas is a thin Gremorie wrapper around ReactFlow from @xyflow/react. It sets the defaults Gremorie expects for AI workflow canvases: panOnScroll, selectionOnDrag, fitView on first render, deletion bound to Backspace and Delete, and a sidebar-toned Background.

Use it for any node-and-edge surface: agent flow editors, prompt graph visualizations, pipeline builders, multi-step LLM routing. Compose with Node, Edge, Connection, Controls, Panel and Toolbar from the same family.

The xyflow stylesheet is imported at the module level (@xyflow/react/dist/style.css), so consuming projects do not need to manage it manually - though importing it once at the app entry is still recommended to avoid order-of-execution surprises.

Preview

3 nodes · 2 edges
'use client';import '@xyflow/react/dist/style.css';import { Canvas, Controls, Panel } from '@gremorie/rx-ai';import {  type Edge as FlowEdge,  type Node as FlowNode,  ReactFlowProvider,} from '@xyflow/react';const canvasNodes: FlowNode[] = [  {    id: '1',    position: { x: 0, y: 0 },    data: { label: 'Prompt' },    type: 'input',  },  {    id: '2',    position: { x: 220, y: -40 },    data: { label: 'Retrieve context' },  },  {    id: '3',    position: { x: 220, y: 80 },    data: { label: 'Generate answer' },    type: 'output',  },];const canvasEdges: FlowEdge[] = [  { id: 'e1-2', source: '1', target: '2' },  { id: 'e1-3', source: '1', target: '3' },];export function CanvasPreview() {  return (    <div className="h-[360px] w-full">      <ReactFlowProvider>        <Canvas edges={canvasEdges} nodes={canvasNodes}>          <Controls />          <Panel position="top-right">            <span className="px-2 text-muted-foreground text-xs">              3 nodes · 2 edges            </span>          </Panel>        </Canvas>      </ReactFlowProvider>    </div>  );}

Anatomy

Canvas                    React Flow viewport
├─ Node …                 nodeTypes (custom renderers)
├─ Edge …                 edgeTypes (Edge.Temporary · Edge.Animated)
├─ Connection             in-progress connection line
└─ overlays (children)    Panel · Controls · Toolbar

Installation

bash npx gremorie@latest add rx-canvas
bash pnpm dlx gremorie@latest add rx-canvas
bash yarn dlx gremorie@latest add rx-canvas
bash bunx --bun gremorie@latest add rx-canvas

Requires @xyflow/react as a peer dependency.

Usage

import { useNodesState, useEdgesState } from "@xyflow/react";
import {
  Canvas,
  Controls,
  Panel,
  Node,
  NodeContent,
  NodeHeader,
  NodeTitle,
} from "@gremorie/rx-ai";

const nodeTypes = { card: (props) => (

  <Node {...props} handles={{ target: true, source: true }}>
    <NodeHeader>
      <NodeTitle>{props.data.label}</NodeTitle>
    </NodeHeader>
    <NodeContent>{props.data.body}</NodeContent>
  </Node>
)};

export function Workflow() {
  const [nodes, , onNodesChange] = useNodesState(initialNodes);
  const [edges, , onEdgesChange] = useEdgesState(initialEdges);

return (

<div className="h-[480px] w-full">
<Canvas
        nodes={nodes}
        edges={edges}
        nodeTypes={nodeTypes}
        onNodesChange={onNodesChange}
        onEdgesChange={onEdgesChange}
      >
<Controls />
<Panel position="top-right">Workflow tools</Panel>
</Canvas>
</div>
);
}

The Angular edition of this component is planned; the React edition is production-ready today.

API

<Canvas>

Forwards all ReactFlowProps from @xyflow/react. The Gremorie wrapper sets these defaults (any prop you pass overrides them):

DefaultValueWhy
deleteKeyCode["Backspace", "Delete"]Both Mac and Windows users can delete the selection.
fitViewtrueOn mount, zoom and pan so all nodes are visible.
panOnDragfalseDragging the canvas selects instead of panning.
panOnScrolltrueTwo-finger trackpad / wheel scroll pans the view.
selectionOnDragtrueDrag from empty space draws a selection box.
zoomOnDoubleClickfalseDouble-click is reserved for node-level actions.

Renders a Background with bgColor="var(--sidebar)" so the canvas matches the surrounding shell.

children are rendered inside the ReactFlow. Use this slot for Controls, Panel, MiniMap, etc.

Composition

  1. <Canvas> owns the surface. Pass nodes, edges, nodeTypes, edgeTypes and the change handlers from xyflow.
  2. Custom node types are React components that render Node from @gremorie/rx-ai with its handles.
  3. <Controls>, <Panel>, <Toolbar> are children that overlay the canvas.
  4. <Connection> is the line that follows the cursor while the user drags from a handle - pass it via the xyflow connectionLineComponent prop.

Variations

Read-only viewer

For visualizing a static flow (e.g. an agent trace), disable interactions.

<Canvas
  nodes={trace.nodes}
  edges={trace.edges}
  nodesDraggable={false}
  nodesConnectable={false}
  elementsSelectable={false}
>
  <Controls showInteractive={false} />
</Canvas>

Editor with custom connection line

Pair with Connection for a Gremorie-themed connection preview.

import { Connection } from '@gremorie/rx-ai';

<Canvas
  nodes={nodes}
  edges={edges}
  connectionLineComponent={Connection}
  onConnect={onConnect}
>
  <Controls />
</Canvas>;

With minimap and panel overlay

import { MiniMap } from '@xyflow/react';

<Canvas nodes={nodes} edges={edges}>
  <Controls />
  <Panel position="top-left">
    <p className="text-xs font-medium">Agent graph</p>
  </Panel>
  <MiniMap pannable zoomable />
</Canvas>;

Accessibility

  • Keyboard: xyflow ships a documented keyboard model - Tab focuses the canvas, then arrow keys nudge selected nodes; Backspace / Delete remove them. Selection box still requires pointer input. For full keyboard parity, supply Panel-level shortcuts.
  • Focus visible: xyflow exposes its own focus ring on the canvas. Do not override outline: none on the root.
  • Reduced motion: Pan and zoom animations honor prefers-reduced-motion via xyflow's internal handling. Custom edge animations (e.g. Connection's animated class) should be wrapped in your own @media (prefers-reduced-motion: reduce) overrides.
  • Screen readers: Nodes are rendered as plain DOM. Ensure each node's content has meaningful text (not just icons), and add aria-label to interactive children inside Node.
  • Node - card-shaped node used inside Canvas
  • Edge - themed edge component
  • Connection - in-progress connection line while dragging
  • Controls - zoom and fit controls docked to a corner
  • Panel - free-floating overlay anchored to a canvas corner
  • Toolbar - per-node floating action bar

On this page