ProcessDiagram Component Hierarchy

How the SVG rendering is structured — from data fetch to pixels

Component Tree
ProcessDiagram — root, fetches layout, manages state
<svg> container with viewBox (zoom/pan transforms)
DiagramSection label="Main Route"
<g> edges layer (rendered first, behind nodes)
DiagramEdge × N — SVG <path> with arrowhead
<g> nodes layer
DiagramNode × N — top-bar card
ConfigBadge × 0..N — tap/trace indicators
NodeToolbar — floating on hover
CompoundNode × 0..N — choice/split container
DiagramNode × N — children inside compound
DiagramSection label="onException" variant="error"
same edge + node structure as above
ZoomControls — HTML overlay (not SVG)
SVG Structure (simplified)
<div class="process-diagram">            /* wrapper div */
  <svg viewBox="0 0 {w} {h}">            /* zoom = viewBox transform */
    <g class="diagram-content">           /* pan offset */

      <!-- Main Route section -->
      <g class="section section--main">
        <g class="edges">
          <path d="M 100 40 C ..." />     /* cubic bezier edge */
          <marker>...</marker>             /* arrowhead def */
        </g>
        <g class="nodes">
          <g transform="translate(x, y)"> /* positioned by ELK */
            <rect .../>                    /* card background */
            <rect .../>                    /* color top bar */
            <text>LOG</text>              /* label */
            <g class="badges">...</g>     /* config indicators */
          </g>
        </g>
      </g>

      <!-- Error Handler section -->
      <g class="section section--error"
         transform="translate(0, {mainH + gap})">
        <text>onException</text>          /* section label */
        <line .../>                        /* divider line */
        <g class="edges">...</g>
        <g class="nodes">...</g>
      </g>

    </g>
  </svg>
  <div class="zoom-controls">...</div>    /* HTML overlay */
</div>
Data Flow
GET /diagrams/{hash}/render?direction=LR
        │
        ▼
  DiagramLayout { nodes[], edges[], width, height }
        │
        ▼
  separateFlows(nodes)  →  mainNodes[] + errorSections[]
        │                       │
        ▼                       ▼
  renderMainSection()    renderErrorSection()
        │                       │
        ▼                       ▼
  SVG groups with              SVG groups offset below
  ELK x/y coordinates         main section by mainHeight + gap