Instruction file imported from gargislalom/so-ai-training-101-pnw-team2 (
.github/instructions/intake/workflows/interactive-mermaid-diagrams.instructions.md). Copyright stays with the author.
Interactive Mermaid Diagrams in Workshop Prototype
Key Files
docs/xd-playground/workshops/prototype/src/components/architecture/MermaidDiagram.tsx- shared rendering componentdocs/xd-playground/workshops/prototype/src/pages/ProgramArchitecturePage.tsx- C1/C2/C3 architecture viewsdocs/xd-playground/workshops/prototype/src/data/c4-model.json- C4 model data sourcedocs/xd-playground/workshops/prototype/src/types/architecture.ts- TypeScript interfaces
Two Click Mechanisms
MermaidDiagram supports two mutually exclusive click mechanisms. Choose based on diagram type.
1. DOM Label Click (mindmaps only)
For mindmap diagrams, use useLabelClick. The component walks SVG <g> elements post-render, extracts visible text, and fires onNodeClick(label) with the text content.
<MermaidDiagram definition={diagram} onNodeClick={handleLabelClick} useLabelClick />
Handler matches label text against known names:
const handleLabelClick = (label: string) => {
const norm = (t: string) => t.replace(/\s+/g, ' ').trim();
const sys = systems.find((s) => norm(s.shortName ?? s.name) === norm(label));
if (sys) navigate(`/systems/${sys.id}`);
};
2. Mermaid Native click Directives (flowcharts)
For graph / flowchart diagrams, DOM-based click detection is unreliable due to nested SVG <g> structure (the <rect> and <text> are siblings, not parent-child). Use Mermaid's native click directive instead.
Requirements:
securityLevel: 'loose'inmermaid.initialize()(already set)MermaidDiagramregisterswindow.__onMermaidNodeClickwhich delegates toonNodeClick
In the diagram definition, add click lines for each clickable node:
// CRITICAL: include parentheses after the function name
def += ` click ${nodeId} call __onMermaidNodeClick()\n`;
In the page component, handle the node ID:
<MermaidDiagram definition={diagram} onNodeClick={handleNodeClick} />
Handler maps Mermaid node IDs to routes:
const handleNodeClick = (nodeId: string) => {
const routes: Record<string, string> = { ndcExt: '/systems/ndc', /* ... */ };
const route = routes[nodeId];
if (route) navigate(route);
};
Common Gotchas
| Issue | Cause | Fix |
|---|---|---|
Parse error ... Expecting 'CALLBACKARGS' |
Missing parentheses | call __onMermaidNodeClick() not call __onMermaidNodeClick |
| Clicks do nothing on flowchart nodes | Using DOM click on flowcharts | Switch to Mermaid click directive |
| Node ID has special chars | Mermaid IDs must be alphanumeric | Use safeId(): id.replace(/[^a-zA-Z0-9]/g, '_') |
| Dev server changes not reflecting | Old port still serving stale code | Check which port Vite is on; restart if needed |
htmlLabels rendering issues |
HTML in labels with SVG mode | flowchart: { htmlLabels: false } is already set; use <br/> and <i> tags in labels |
Adding a New Domain C2 Diagram
-
Populate data in
c4-model.jsonundercomponents["{domainId}"]array followingC4Componentschema:{ "id": "...", "name": "...", "type": "Service", "description": "...", "featureTitle": "Layer Name", "systems": ["sap"] } -
Build diagram function returning a Mermaid
graph TBstring with subgraphs per architectural layer. Addclickdirectives for every clickable node. -
Wire routing in
buildC2Diagram():if (domainId === 'your-domain') return buildYourDomainC2Diagram(); -
Map node IDs to routes in a helper function, used by
handleNodeClickin C2View.
See buildBankruptcyC2Diagram() and getBkNodeRoutes() in ProgramArchitecturePage.tsx as the reference implementation.
Adding Click to C1 Mindmap Boundary Labels
Boundary labels (like "Bankruptcy") in the C1 mindmap auto-navigate to domains. The handleLabelClick in C1View already matches labels against both externalSystems and domains arrays. No click directive needed - mindmaps use DOM label matching.