feat(flowchart): Add highlight and drag node interaction#7318
feat(flowchart): Add highlight and drag node interaction#7318vicaya wants to merge 4 commits intomermaid-js:developfrom
Conversation
🦋 Changeset detectedLatest commit: cf07a49 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
✅ Deploy Preview for mermaid-js ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
@mermaid-js/examples
mermaid
@mermaid-js/layout-elk
@mermaid-js/layout-tidy-tree
@mermaid-js/mermaid-zenuml
@mermaid-js/parser
@mermaid-js/tiny
commit: |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #7318 +/- ##
==========================================
- Coverage 3.52% 3.50% -0.02%
==========================================
Files 509 509
Lines 49790 50037 +247
Branches 785 785
==========================================
Hits 1754 1754
- Misses 48036 48283 +247
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
|
/retest |
a205e2e to
59c680d
Compare
|
Hi @vicaya, apologies for the long silence on this one: it got buried during a busy stretch, and that's on me. I appreciate the work you've put into this. |
knsv
left a comment
There was a problem hiding this comment.
[sisyphus-bot]
Thanks for tackling this, @vicaya — interactive flowcharts are a compelling feature and we appreciate the effort here. Apologies for the long wait on review; let's work through the feedback and get this into shape.
What's working well
🎉 [praise] Nice UX touch with clickDistance(3) to disambiguate click vs. drag — thoughtful detail that prevents accidental highlighting when dragging.
🎉 [praise] The CSS-only highlighting approach using filter: drop-shadow() via CSS classes instead of inline styles is clean and maintainable.
🎉 [praise] E2E tests cover both the enabled and disabled interaction paths — good coverage of the config toggle.
🎉 [praise] The config.schema.yaml change follows the correct schema-first pattern, and the changeset is included with the right semver bump (minor).
Things to address
🔴 [blocking] — config.type.ts manually edited (generated file)
packages/mermaid/src/config.type.ts:330-337 — This file is auto-generated from config.schema.yaml via pnpm run --filter mermaid types:build-config. It must never be edited by hand — CI will fail on types:verify-config. Your schema change looks correct; it would be great to just delete the manual edit and regenerate the types from the schema instead.
🔴 [blocking] — enableInteraction defaults to true — breaking behavioral change
packages/mermaid/src/schemas/config.schema.yaml:2196 — Mermaid is rendered server-side by GitHub, GitLab, Docusaurus, Obsidian, and many other platforms. Defaulting to true means every existing flowchart suddenly gets draggable, clickable-to-highlight nodes. This would break SSR environments (no DOM events), read-only viewers, and change the behavior of millions of existing documents. The default needs to be false so this is opt-in.
🔴 [blocking] — 370+ lines of rendering/interaction logic in the DB module
packages/mermaid/src/diagrams/flowchart/flowDb.ts:37-280 — The entire SVG path parser, drag handler, edge update logic, and highlight code lives in flowDb.ts. The DB's role in the Mermaid architecture is to store parsed data (DiagramDB contract). While setupToolTips sets a precedent for post-render DOM work in the DB via bindFunctions, that's ~30 lines. This adds 370+ lines of complex SVG geometry, D3 drag state machines, and edge path manipulation — it substantially changes the character of the module.
It would be great to extract the helper functions (parsePathD, reconstructPathD, updateConnectedEdges, highlightConnectedEdges, cleanNodeId, createEdgePatterns — ~180 lines) into a separate flowInteraction.ts file within the flowchart diagram folder. The setupInteraction method in the DB can then delegate to that module, keeping the DB thin.
🟡 [important] — Drag rearrangements are ephemeral and not communicated to users
The drag-to-rearrange feature modifies SVG positions directly in the DOM after rendering. These changes are not part of the diagram markup and are not persisted — they don't update the diagram source text, and any re-render (window resize, theme change, config update, or calling mermaid.run() again) silently discards the user's rearrangement. This is inherent to operating outside the markup, but the documentation and UX should make this crystal clear. Without that, users will spend time carefully arranging nodes only to lose their work unexpectedly. Worth considering at minimum a prominent note in the docs, and ideally a visual indicator (e.g., a subtle "layout modified" badge) that the diagram state has diverged from the source.
🟡 [important] — Hardcoded highlight colors instead of theme variables
packages/mermaid/src/diagrams/flowchart/styles.ts:190,202 — rgba(0, 100, 200, 0.6) and rgba(0, 0, 0, 0.5) are hardcoded. Mermaid has 5 themes (default, dark, forest, neutral, base), and a fixed blue glow won't suit all of them. These should derive from theme variables (e.g., ${options.primaryColor} or a new highlightColor variable), following the pattern used throughout styles.ts.
🟡 [important] — New drag/click handlers may swallow existing click callbacks
Flowcharts already support user-defined click handlers (click A callback syntax) which wire up native addEventListener('click', ...) on nodes (flowDb.ts:520-532). The new D3 drag handler intercepts all pointer events on g.node elements. When a node has both a user-defined click callback and the interaction handler, the D3 drag's on('end') handles the "click" case for highlighting but doesn't propagate to or check for existing native click listeners. It would be worth checking whether nodes have haveCallback or a link set and either skipping the interaction setup for those nodes or ensuring existing click handlers still fire.
🟡 [important] — SVG path parser doesn't handle relative commands
packages/mermaid/src/diagrams/flowchart/flowDb.ts:62 — parsePathD calls match[1].toUpperCase() on every command letter, treating relative commands (lowercase m, l, c, etc.) as absolute. Relative commands define coordinates relative to the current point, not the origin. While mermaid's current edge rendering likely produces absolute paths only, this is an undocumented assumption. At minimum, worth adding a comment documenting this limitation; ideally, resolving relative to absolute in the parser.
🟡 [important] — Edge ID pattern matching couples to internal naming
packages/mermaid/src/diagrams/flowchart/flowDb.ts:161-167 — createEdgePatterns builds regexes like ^L_${nodeId}_ to find connected edges. This couples to the internal L_source_target_index naming convention (from getEdgeId in utils.ts). If the edge ID format changes, this breaks silently. A data-driven approach using the DB's edge list to look up connected edges by source/target would be more robust.
🟡 [important] — Unit tests don't cover the actual interaction logic
packages/mermaid/src/diagrams/flowchart/flowDb.spec.ts:184-203 — The two new tests only verify bindFunctions is a function and is callable after clear(). The core logic — parsePathD, reconstructPathD, cleanNodeId, createEdgePatterns, edge highlighting — is entirely untested at the unit level. These are pure functions that are highly suitable for unit testing. The e2e tests cover the happy path but won't catch edge cases in path parsing or reconstruction.
🟢 [nit] — !important in CSS
packages/mermaid/src/diagrams/flowchart/styles.ts:207 — cursor: grabbing !important suggests a specificity issue. Worth checking if increasing selector specificity can avoid !important.
💡 [suggestion] — Documentation wording
packages/mermaid/src/docs/syntax/flowchart.md:1023 — "Slow clicking a node would highlight..." reads oddly. The clickDistance(3) just distinguishes clicks from drags; no "slowness" is needed. Something like "Click a node to highlight it and its connected edges. Drag a node to rearrange the layout." would be clearer.
Tally: 🔴 3 / 🟡 6 / 🟢 1 / 💡 1 / 🎉 4
Looking forward to seeing the next iteration — the core idea is solid and this will be a great addition once these items are addressed. Let's get it across the finish line! 🚀
📑 Summary
Adds interactive features to flowchart diagrams: click-to-highlight nodes and connected edges with drop shadows, and drag-to-rearrange node positions with edges following the dragged node.
Resolves #5883
Configuration Options
flowchart.enableInteraction(boolean, default: true) - Enables/disables interactive featuresInteractions
Implementation Details
filter: drop-shadow()for highlighting (no inline styles).edgePaths) and newer rendering (.edges) pathsclickDistance(3)to distinguish clicks from dragsDemo & Testing
demos/flowchart.htmlfor testing against dark backgroundscypress/integration/rendering/flowchart-interaction.spec.ts📋 Tasks
Make sure you
MERMAID_RELEASE_VERSIONis used for all new features.pnpm changesetand following the prompts. Changesets that add features should beminorand those that fix bugs should bepatch. Please prefix changeset messages withfeat:,fix:, orchore:.