Skip to content

feat(flowchart): collapsible subgraphs via @{ view: collapsed }#7785

Open
knsv-bot wants to merge 3 commits into
developfrom
feature/7784_collapsible-subgraphs
Open

feat(flowchart): collapsible subgraphs via @{ view: collapsed }#7785
knsv-bot wants to merge 3 commits into
developfrom
feature/7784_collapsible-subgraphs

Conversation

@knsv-bot

Copy link
Copy Markdown
Collaborator

Summary

Resolves #7784

Adds opt-in collapsible subgraphs to the flowchart. A subgraph annotated with @{ view: collapsed } is rendered as a single compact node instead of an expanded container:

  • Internal nodes of the collapsed subgraph are hidden.
  • Edges that cross the subgraph boundary are redirected to the collapsed node.
  • Edges entirely internal to a collapsed subgraph are dropped (they would become self-loops).
  • Nested collapses resolve to the outermost collapsed ancestor.
flowchart TD
  Start --> one
  subgraph one [My Group]
    A --> B
    B --> C
  end
  one --> End
  one@{ view: collapsed }
Loading

How it works

  • The metadata is attached via the existing id@{ ... } statement syntaxaddVertex detects when the id refers to a declared subgraph and routes the metadata onto it. No grammar change is required.
  • The collapse/redirect logic lives entirely in flowDb.getData().
  • A new additive collapsedGroup shape renders the compact node (title + dashed separator + ellipsis indicator), reusing the cluster theme variables.

Classification

  • Change type: flowchart DB/renderer + additive shared rendering-util (new shape)
  • Breaking change: No — feature is opt-in via new view: collapsed syntax; existing diagrams produce identical output. The new shape is purely additive.
  • Shared code touched: Yes — new rendering-util/rendering-elements/shapes/collapsedGroup.ts + one registration entry in shapes.ts (additive only; follows the existing pattern for kanbanItem/classBox/erBox).

Verification

  • TDD: 4/4 collapse tests failed before the fix, all pass after
  • Lint: passed (0 errors)
  • Unit tests: passed (vitest run packages/mermaid/src/diagrams/flowchart/)
  • E2E snapshot tests: added in cypress/integration/rendering/flowchart/flowchart-v2.spec.js (collapsed, side-by-side, hand-drawn, nested)
  • comp-review-changes: passed (0 blockers)
  • Visual spot-check: verified all 5 scenarios via agent-browser — collapsed node + indicator, edge redirect, nested→outermost, hand-drawn
  • Full Cypress e2e: not run locally (environment requires Chrome --no-sandbox; suite is heavy) — covered by the new snapshot tests in CI
  • Changeset: generated (minor)

A subgraph annotated with `@{ view: collapsed }` now renders as a single
compact node. Its internal nodes are hidden and edges crossing the subgraph
boundary are redirected to the collapsed node; nested collapses resolve to
the outermost collapsed ancestor.

Subgraph metadata is routed through the existing `id@{ ... }` statement
syntax in addVertex, so no grammar change is required. A new `collapsedGroup`
shape renders the compact node with a title and an ellipsis indicator.

Resolves #7784
@changeset-bot

changeset-bot Bot commented May 29, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5f7d987

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
mermaid Minor

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

@netlify

netlify Bot commented May 29, 2026

Copy link
Copy Markdown

Deploy Preview for mermaid-js ready!

Name Link
🔨 Latest commit 5f7d987
🔍 Latest deploy log https://app.netlify.com/projects/mermaid-js/deploys/6a1948159bf0770008f5f9fe
😎 Deploy Preview https://deploy-preview-7785--mermaid-js.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@pkg-pr-new

pkg-pr-new Bot commented May 29, 2026

Copy link
Copy Markdown

Open in StackBlitz

@mermaid-js/examples

npm i https://pkg.pr.new/@mermaid-js/examples@7785

mermaid

npm i https://pkg.pr.new/mermaid@7785

@mermaid-js/layout-elk

npm i https://pkg.pr.new/@mermaid-js/layout-elk@7785

@mermaid-js/layout-tidy-tree

npm i https://pkg.pr.new/@mermaid-js/layout-tidy-tree@7785

@mermaid-js/mermaid-zenuml

npm i https://pkg.pr.new/@mermaid-js/mermaid-zenuml@7785

@mermaid-js/parser

npm i https://pkg.pr.new/@mermaid-js/parser@7785

@mermaid-js/tiny

npm i https://pkg.pr.new/@mermaid-js/tiny@7785

commit: 5f7d987

@knsv knsv marked this pull request as ready for review May 29, 2026 06:40
@codecov

codecov Bot commented May 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 201 lines in your changes missing coverage. Please review.
✅ Project coverage is 3.24%. Comparing base (23a9c15) to head (5f7d987).
⚠️ Report is 16 commits behind head on develop.

Files with missing lines Patch % Lines
packages/mermaid/src/diagrams/flowchart/flowDb.ts 0.00% 99 Missing ⚠️
...g-util/rendering-elements/shapes/collapsedGroup.ts 0.00% 98 Missing ⚠️
packages/mermaid/src/diagrams/flowchart/styles.ts 0.00% 2 Missing ⚠️
...id/src/rendering-util/rendering-elements/shapes.ts 0.00% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           develop   #7785      +/-   ##
==========================================
- Coverage     3.25%   3.24%   -0.01%     
==========================================
  Files          600     601       +1     
  Lines        60960   61143     +183     
  Branches       917     918       +1     
==========================================
  Hits          1986    1986              
- Misses       58974   59157     +183     
Flag Coverage Δ
unit 3.24% <0.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
packages/mermaid/src/diagrams/flowchart/types.ts 100.00% <ø> (ø)
packages/mermaid/src/types.ts 100.00% <ø> (ø)
packages/mermaid/src/diagrams/flowchart/styles.ts 2.04% <0.00%> (-0.09%) ⬇️
...id/src/rendering-util/rendering-elements/shapes.ts 0.22% <0.00%> (-0.01%) ⬇️
...g-util/rendering-elements/shapes/collapsedGroup.ts 0.00% <0.00%> (ø)
packages/mermaid/src/diagrams/flowchart/flowDb.ts 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@argos-ci

argos-ci Bot commented May 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) 👍 Changes approved 5 added May 29, 2026, 8:15 AM

Covers an edge that targets the deepest node (two levels in) while the
outermost subgraph is collapsed — the edge should redirect to the outermost
collapsed node.

@ashishjain0512 ashishjain0512 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[sisyphus-bot]

Thanks for this — collapsible subgraphs is a frequently requested feature (#7784) and this is a really clean take on it. I read the full diff, ran an XSS/injection pass over the new shape and the metadata-routing changes, and verified the collapse/redirect logic against the unit and parser tests. Summary below; one important gap (docs) and a few small polish items, nothing blocking.

What's working well

  • 🎉 Reusing id@{ ... } instead of a grammar change. Routing subgraph metadata through the existing addVertex path (flowDb.ts:154 area) is exactly the right call — it avoids touching the JISON grammar, keeps the syntax consistent with node metadata, and means zero parser-regression risk. Nicely reasoned in the commit message too.
  • 🎉 Excellent test coverage for the scope. Unit tests in flowDb.spec.ts cover the normal-group baseline, collapse-to-single-node, boundary-edge redirect, internal-edge drop (self-loop avoidance), and nested outermost-ancestor resolution. The parser test and five e2e snapshots (including a handDrawn case and a deeply-nested redirect) round it out. This is the kind of coverage that makes a shared-rendering change safe to merge.
  • 🎉 Hand-drawn mode implemented from the start in collapsedGroup.ts via the rough.js path — not deferred, which is great.
  • 🎉 The edge-redirect logic is genuinely correct. I traced the outermostCollapsed containment walk (with the seen cycle guard) and the self-loop-vs-internal-edge distinction — the start === end && (map.has(start) || map.has(end)) guard correctly drops internal edges while preserving real self-loops on uncollapsed nodes. The nested case resolving to the outermost ancestor is handled well.

Security

XSS/injection review: clean. The @{ view: ... } value is parsed via yaml.load, only ever compared === 'collapsed' to select a literal shape string, and never reaches a DOM sink. The subgraph title flows through the same shared labelHelper (which sanitizes) as the existing expanded rect branch, and the new shape emits only plain rect/line/circle nodes that pass through the normal DOMPurify boundary. No new tags/attributes, no foreignObject/<use>/event handlers. No widening of the attack surface.

Things to address

  • 🟡 [important] Missing user-facing documentation for the new syntax. This PR introduces a brand-new public syntax (subgraphId@{ view: collapsed }) but adds no docs in packages/mermaid/src/docs/syntax/flowchart.md (the only doc changes are the auto-generated interface line-number shifts). The subgraphs section is around flowchart.md:894 — it'd be great to add a short subsection there with an example, so the feature is discoverable. Remember to use the MERMAID_RELEASE_VERSION placeholder for the version.

Nits & suggestions

  • 🟢 [nit] Import ordering in shapes.ts:6collapsedGroup is inserted between bowTieRect and card, but alphabetically it sorts after card (ca < co). Minor, just for consistency with the rest of the block.
  • 🟢 [nit] collapsedGroup.ts:585const labelEl = shapeSvg.select('.label'); if (labelEl) is always truthy (d3 select returns a non-null selection even when empty). If the intent is to guard against a missing label, use if (!labelEl.empty()). Harmless as-is since .attr() on an empty selection is a no-op.
  • 💡 [suggestion] When several edges from the same external node target different internal members of one collapsed subgraph (e.g. X-->A and X-->B with A,B collapsed), they redirect to two parallel X-->collapsed edges with distinct counter-based ids. Functionally fine, but it renders as duplicate arrows. Deduplicating redirected edges on (start, end, label) could tidy that up — worth considering, not required for this PR.
  • 💡 [suggestion] The early return in the new subgraph-metadata branch of addVertex means any subgraphId@{ ... } now routes all keys to subGraph.metadata (only view is consumed) and skips vertex creation. That's the right behavior for view, but worth a one-line comment noting other metadata keys on a subgraph id are intentionally ignored, so a future reader doesn't expect e.g. shape to apply there.

Really solid work overall — once the docs are in, this is good to go. Let me know if you'd like a hand with the docs example. 🚀

🤖 Automated review. Severity: 0 blocking / 1 important / 2 nit / 2 suggestion / 4 praise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add metadata to handle expand/collapsing of subgraphs

2 participants