|
| 1 | +# ForceGraphComponent |
| 2 | + |
| 3 | +An interactive D3 force-directed graph custom component for Retool. Visualises node-link data with dynamic grouping, multiple themes, zoom controls, and a detail panel. |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## Features |
| 8 | + |
| 9 | +- `Force-directed layout` via D3 with drag, zoom, and pan |
| 10 | +- `Auto node grouping` — detects a model, category, or any suitable key and colour-codes nodes accordingly |
| 11 | +- `4 preset themes` — Arctic, Midnight, Rose Gold, Slate Pro |
| 12 | +- `Custom theme editor` — live colour pickers for background, grid, edges, labels, node strokes, per-group node colours, and tooltip |
| 13 | +- `Info panel` — click any node to inspect all its fields; shows a graph summary when nothing is selected |
| 14 | +- `Hover tooltip` — displays node name, group value, and a prompt to click |
| 15 | +- `Zoom controls` — zoom in, zoom out, reset |
| 16 | +- `Stable rendering` — data identity is tracked by content, not object reference, so the simulation only rebuilds when data actually changes |
| 17 | +- `Persisted preferences` — active theme and custom colour overrides survive page refresh via localStorage |
| 18 | + |
| 19 | +--- |
| 20 | + |
| 21 | +## Input |
| 22 | +The component accepts a single Retool state object named `graphData`. |
| 23 | + |
| 24 | +Schema |
| 25 | +```json |
| 26 | +{ |
| 27 | + "nodes": [ |
| 28 | + { |
| 29 | + "id": "string | number", |
| 30 | + "name": "string", |
| 31 | + "model": "string (optional)", |
| 32 | + "category": "string (optional)", |
| 33 | + "avgLatency": "number (optional)", |
| 34 | + "avgCost": "number (optional)", |
| 35 | + "numCalls": "number (optional)", |
| 36 | + "performanceScore": "number (optional)" |
| 37 | + } |
| 38 | + ], |
| 39 | + "links": [ |
| 40 | + { |
| 41 | + "source": "string | number (node id)", |
| 42 | + "target": "string | number (node id)", |
| 43 | + "weight": "number (optional, default 1)" |
| 44 | + } |
| 45 | + ] |
| 46 | +} |
| 47 | +``` |
| 48 | + |
| 49 | +--- |
| 50 | + |
| 51 | + |
| 52 | +Any additional fields on a node are displayed in the `All Fields` section of the info panel. |
| 53 | + |
| 54 | +Example |
| 55 | +```json |
| 56 | +{ |
| 57 | + "nodes": [ |
| 58 | + { "id": "1", "name": "Classifier", "model": "GPT-4", "numCalls": 120, "avgLatency": 340 }, |
| 59 | + { "id": "2", "name": "Summariser", "model": "Claude", "numCalls": 80, "avgCost": 0.002 }, |
| 60 | + { "id": "3", "name": "Embedder", "model": "GPT-3.5", "numCalls": 200 } |
| 61 | + ], |
| 62 | + "links": [ |
| 63 | + { "source": "1", "target": "2", "weight": 2 }, |
| 64 | + { "source": "2", "target": "3" } |
| 65 | + ] |
| 66 | +} |
| 67 | +``` |
| 68 | + |
| 69 | + |
| 70 | +--- |
| 71 | + |
| 72 | + |
| 73 | +## Automatic grouping |
| 74 | + |
| 75 | +The component scans all node keys in order — model, category, then any other key — and picks the first one that has between 2 and 20 distinct values. That key becomes the group key, used to colour nodes and populate the legend in the info panel. |
| 76 | +To disable grouping, ensure no key on your nodes produces 2–20 distinct values |
| 77 | + |
| 78 | +--- |
| 79 | + |
| 80 | +# Theming |
| 81 | + |
| 82 | +## Preset themes |
| 83 | + |
| 84 | +Select from the theme bar at the bottom of the component: `Arctic, Midnight, Rose Gold, Slate Pro`. |
| 85 | + |
| 86 | +## Custom theme |
| 87 | + |
| 88 | +Click ✏️ `Custom` to open the colour editor. Changes to background, grid, edges, labels, node stroke, and tooltip colours apply instantly. Edits to per-group node colours also apply immediately and automatically activate the custom theme — no need to click Apply Custom Theme first. |
| 89 | +Click `↺ Reset` to restore the last selected preset and clear all custom colour overrides. |
0 commit comments