Overview
Frontend workflow nodes are React Flow nodes. Prefer the shared WorkflowNode wrapper from @quan-erp/base-frontend — do not import relative copies from base source. Pair with Backend → @Workflow.
- Props from React Flow: { id, data, selected?}
- Simple nodes — createDefaultWorkflowNodeComponent
- Custom handles / styling — WorkflowNode + @xyflow/react Handle
- Register the node component for the workflow designer to discover
1. Default node
TSXdefault
1import { AlarmClock } from "@icon-park/react";
2import { createDefaultWorkflowNodeComponent } from "@quan-erp/base-frontend";
3import metadata from "../../module.metadata.json" with { type: "json" };
4
5export const OnBookingWorkflowNode = createDefaultWorkflowNodeComponent({
6 defaultIcon: <AlarmClock size={20} />,
7 defaultLabel: "On Hotel booking",
8 pluginName: metadata.name,
9 defaultIconBg:
10 "bg-pink-50 dark:bg-pink-950/40 text-pink-600 dark:text-pink-400",
11 hasOutput: true,
12 hasInput: false,
13});2. Custom WorkflowNode
- WorkflowNode supplies card chrome, play, and delete controls
- Pass Handle children for custom ports
- Use ! important classes when overriding defaults
TSXcustom
1import { Handle, Position } from "@xyflow/react";
2import { Tool } from "@icon-park/react";
3import { WorkflowNode } from "@quan-erp/base-frontend";
4import metadata from "../../module.metadata.json" with { type: "json" };
5
6export function CustomNode({
7 id,
8 data,
9 selected,
10}: {
11 id: string;
12 data: { label?: string };
13 selected?: boolean;
14}) {
15 return (
16 <WorkflowNode
17 pluginName={metadata.name}
18 id={id}
19 data={data}
20 selected={selected}
21 defaultIcon={<Tool size={18} theme="outline" />}
22 defaultLabel="Custom Tool"
23 defaultIconBg="bg-yellow-50 text-yellow-600"
24 >
25 <Handle type="source" id="output" position={Position.Top} />
26 </WorkflowNode>
27 );
28}