Appearance
Graph Panel
GraphPreview
Force-directed graph visualization of money flows between accounts and categories. Nodes represent accounts and expense categories; edges represent transaction flows between them.
Chart Type
| Property | Value |
|---|---|
| Library | Apache ECharts (raw echarts.init()) |
| Series type | graph with layout: 'force' |
| Rendering | Canvas, direct init (NOT BaseChart) |
| Resize handling | Manual ResizeObserver on container |
| Source file | src/components/panels/GraphPanel.tsx |
The panel bypasses BaseChart intentionally to avoid re-mount issues with the force layout. A raw echarts.init() call is made on a container div, with a dedicated ResizeObserver wired for responsive resizing.
What It Shows
- Nodes -- bank accounts and spending categories, sized by transaction volume
- Edges -- transaction flows between accounts and categories, width scaled by flow amount
- Adjacency highlighting -- hovering a node highlights its connected edges in that node's color
Node Coloring
| Account Type | Color |
|---|---|
| CHECKING | Accent (#00d4aa) |
| SAVINGS | Accent (#00d4aa) |
| CREDIT | Danger (red) |
| INVESTMENT | Warning (amber) |
| Categories | Per-category color from CATEGORY_COLORS |
Custom color groups override the defaults when a node name matches the group's search query.
Interactivity
Full-Canvas Pan and Zoom
ECharts' built-in roam is disabled. Instead, custom mouse handlers provide unbounded navigation:
- Drag-pan -- click and drag anywhere on the canvas to pan
- Scroll-wheel zoom -- zooms toward the mouse cursor position (range: 0.1x to 15x)
- Fit-to-bounds -- auto-fits the graph on initial load; re-center via the header button
Manual Adjacency Highlight
The built-in focus: 'adjacency' emphasis is supplemented with a manual implementation that:
- Builds an adjacency map of node-to-edge indices on each option update
- On
mouseover, dispatches highlight actions for the hovered node, its neighbors, and connected edges - Overrides edge stroke color to match the hovered node's color
- On
mouseout, dispatchesdownplayand forces a zrender refresh
Node Dragging
Individual nodes are draggable (draggable: true) within the force layout. The force simulation runs with animation: false for instant layout.
Settings Sidebar
A 220px collapsible sidebar (toggled via the gear icon in the header) with 5 sections:
1. Filters
| Control | Description |
|---|---|
| Text filter | Filters nodes by name substring match |
| Accounts toggle | Show/hide account nodes |
| Categories toggle | Show/hide category nodes |
| Orphans toggle | Show/hide nodes with no connections |
2. Groups
| Control | Options |
|---|---|
| Grouping mode | By Type, By Bank, By Category Type, None |
| Color groups | Custom search-query-to-color mappings with add/remove |
3. Display
| Control | Range |
|---|---|
| Labels | On/Off |
| Arrows | On/Off (edge arrow symbols) |
| Node Size | 5 -- 80 |
| Link Thickness | 1 -- 10 |
| Label Size | 6 -- 18 |
| Label Opacity | 0% -- 100% |
| Node Opacity | 0.1 -- 1.0 |
| Link Style | Straight, Curved, Dashed |
| Node Shape | Circle, Square, Rounded Square, Diamond |
4. Forces
| Control | Range |
|---|---|
| Center Force (gravity) | 0 -- 0.5 |
| Repel Force | 5 -- 500 |
| Link Distance Min | 1 -- 200 |
| Link Distance Max | 5 -- 400 |
| Friction | 0 -- 1 |
5. Restore Defaults
Resets all settings to their initial values via useGraphStore.resetToDefaults().
Data Source
| Store | Fields |
|---|---|
useFinanceStore | accounts, transactions, categories |
useGraphStore | All layout/display/force settings, settingsOpen |
useChartTheme | Theme colors for tooltips, labels, borders |
Empty State
Displays "No transaction data" centered in the panel when transactions.length === 0.