Problem
dag-map has no concept of "selected" or "highlighted" nodes. When a consumer needs to visually distinguish certain nodes (e.g., a clicked node, a pinned node, a search result), there is no built-in mechanism. Consumers must choose between:
-
CSS overrides on g[data-node-id] — toggling a class externally and styling with CSS. This conflicts with heatmap mode where node fills are set inline, and with the dim feature which also manipulates opacity.
-
renderNode override — writing a full custom node renderer just to add a selection ring. This is heavy: the consumer must replicate all of dag-map's default rendering (circle size by degree, interchange inner circle, gate dashes, dim opacity, metric label) just to add one visual detail.
-
Post-render DOM mutation — querying circle[data-id="X"] and changing attributes. Fragile, lost on re-render, and fights with heatmap coloring.
None of these compose well with existing features (heatmap, dim, gate nodes).
Context
The FlowTime UI workbench paradigm requires a clear visual distinction between:
- Default nodes (metric-colored, normal)
- Selected/pinned nodes (user clicked to inspect — should stand out)
- Dimmed nodes (already supported via
dim: true)
Another project using dag-map may have similar needs (e.g., highlighting a search result or an active execution node).
Proposed Design
Option A: selected set in render options
Add an optional selected: Set<string> (or string[]) to renderSVG options:
renderSVG(dag, layout, {
metrics: metricsMap,
selected: new Set(['api_svc', 'db_pool']),
})
Selected nodes get a visual indicator that composes with all existing modes:
- Selection ring: An outer circle with slightly larger radius, contrasting stroke (e.g., theme
ink color), and higher opacity. Sits behind the node circle.
- Works with heatmap: The metric fill is preserved; the ring is additive.
- Works with dim: A selected+dimmed node shows the ring at full opacity but the node itself at dim opacity (selection overrides dim for the ring only).
SVG output for a selected node:
<g data-node-id="api_svc" data-node-cls="core" data-selected="true">
<!-- Selection ring (behind node) -->
<circle cx="95" cy="160" r="9" fill="none" stroke="#3B3530" stroke-width="2" opacity="0.6"/>
<!-- Normal node circle -->
<circle data-id="api_svc" cx="95" cy="160" r="5.25" fill="#F5F0E8" stroke="#D4944C" stroke-width="2.4"/>
<text ...>api_svc</text>
</g>
The data-selected="true" attribute enables CSS-based enhancement if consumers want more (e.g., animation, glow).
Option B: nodeState map for extensible states
Instead of a single selected set, accept a state map:
renderSVG(dag, layout, {
nodeState: new Map([
['api_svc', 'selected'],
['db_pool', 'highlighted'],
['auth', 'error'],
]),
})
Each state maps to a visual treatment defined by the theme:
// Theme extension
{
states: {
selected: { ring: true, ringColor: ink, ringOpacity: 0.6 },
highlighted: { ring: true, ringColor: '#FFD700', ringOpacity: 0.8 },
error: { ring: true, ringColor: '#FF4444', ringOpacity: 0.9 },
}
}
Recommendation
Start with Option A — selected: Set<string> covers the immediate need (workbench pinning, search results) with minimal API surface. The selection ring is a single visual treatment, well-defined, composable with heatmap and dim.
Evolve to Option B if multiple distinct states prove necessary. The migration path is smooth: selected becomes nodeState with backward compatibility.
Visual Behavior
| State Combination |
Node Circle |
Selection Ring |
Label |
| Default |
metric color or class color |
none |
normal |
| Selected |
metric color or class color |
theme ink, r+3, opacity 0.6 |
bold or normal |
| Dimmed |
faded (dimOpacity) |
none |
faded |
| Selected + Dimmed |
faded |
full opacity ring |
faded label |
| Selected + Heatmap |
metric color fill |
ring in contrasting color |
metric label |
Benefits
- Single option, no breaking changes
- Composes with heatmap, dim, gate, interchange — no conflicts
data-selected attribute enables CSS-based animation if wanted
- Clean SVG output (one extra circle per selected node)
- Selection ring is theme-aware (uses
ink color by default)
Problem
dag-map has no concept of "selected" or "highlighted" nodes. When a consumer needs to visually distinguish certain nodes (e.g., a clicked node, a pinned node, a search result), there is no built-in mechanism. Consumers must choose between:
CSS overrides on
g[data-node-id]— toggling a class externally and styling with CSS. This conflicts with heatmap mode where node fills are set inline, and with thedimfeature which also manipulates opacity.renderNodeoverride — writing a full custom node renderer just to add a selection ring. This is heavy: the consumer must replicate all of dag-map's default rendering (circle size by degree, interchange inner circle, gate dashes, dim opacity, metric label) just to add one visual detail.Post-render DOM mutation — querying
circle[data-id="X"]and changing attributes. Fragile, lost on re-render, and fights with heatmap coloring.None of these compose well with existing features (heatmap, dim, gate nodes).
Context
The FlowTime UI workbench paradigm requires a clear visual distinction between:
dim: true)Another project using dag-map may have similar needs (e.g., highlighting a search result or an active execution node).
Proposed Design
Option A:
selectedset in render optionsAdd an optional
selected: Set<string>(orstring[]) torenderSVGoptions:Selected nodes get a visual indicator that composes with all existing modes:
inkcolor), and higher opacity. Sits behind the node circle.SVG output for a selected node:
The
data-selected="true"attribute enables CSS-based enhancement if consumers want more (e.g., animation, glow).Option B:
nodeStatemap for extensible statesInstead of a single
selectedset, accept a state map:Each state maps to a visual treatment defined by the theme:
Recommendation
Start with Option A —
selected: Set<string>covers the immediate need (workbench pinning, search results) with minimal API surface. The selection ring is a single visual treatment, well-defined, composable with heatmap and dim.Evolve to Option B if multiple distinct states prove necessary. The migration path is smooth:
selectedbecomesnodeStatewith backward compatibility.Visual Behavior
ink, r+3, opacity 0.6Benefits
data-selectedattribute enables CSS-based animation if wantedinkcolor by default)