Skip to content

fix(mermaid): Mermaid lazy render when tab becomes visible#12281

Closed
yoshibase wants to merge 1 commit into
facebook:mainfrom
yoshibase:fix/issue-8357-mermaid-tabs
Closed

fix(mermaid): Mermaid lazy render when tab becomes visible#12281
yoshibase wants to merge 1 commit into
facebook:mainfrom
yoshibase:fix/issue-8357-mermaid-tabs

Conversation

@yoshibase

@yoshibase yoshibase commented Jul 13, 2026

Copy link
Copy Markdown

Summary

Fixes #8357

Mermaid diagrams inside inactive tab panels render with missing arrow markers. The root cause is rendering while the SVG is hidden (zero-size container), not a Mermaid syntax issue.

Note: @slorber's review pointed out that the IntersectionObserver approach here is too narrow (tabs only) and does not address concurrent renders of multiple visible diagrams (#8357 comment). I am keeping this PR open while I rework the approach. The test plan below documents how to reproduce the original bug and how I verified the tab case locally.

Reproducing the bug (on main)

Known-good reference on docusaurus.io: https://docusaurus.io/tests/pages/diagrams#mermaid-in-tabs

To reproduce in a fresh site:

  1. Enable @docusaurus/theme-mermaid in docusaurus.config.js.
  2. Create a docs page with non-lazy tabs and a diagram in each tab:
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

<Tabs>
  <TabItem value="a" label="Tab A">

```mermaid
graph LR
  a --> c(10)
  b --> c(10)
```

  </TabItem>
  <TabItem value="b" label="Tab B" default>

```mermaid
graph LR
  d --> z(42)
  e --> z(42)
```

  </TabItem>
</Tabs>
  1. Run npm start and open the page in Chrome.
  2. Open Tab B (or whichever tab was hidden on first load).
  3. Bug: arrow heads on the edges are missing or broken. Tab A (visible on first paint) looks fine.

What to look for in DevTools

  1. Right-click a broken arrow → Inspect.
  2. In the SVG, look for <marker> definitions in <defs> and marker-end attributes on <path> elements.
  3. On the broken tab, markers are often missing or reference IDs that were not defined because Mermaid ran while the container had display: none / zero size.

Test plan for this PR's approach (tab visibility)

Preview: deploy preview for PR #12281 (Netlify bot comment on the PR)

  1. Open the preview at the same mermaid-in-tabs test page (or the repro MDX above if added to the preview build).
  2. Load the page with Tab B hidden, then click Tab B.
  3. Expected with fix: both tabs show intact arrow heads on all edges.
  4. Compare side-by-side with main on the same page.

Side-by-side diagrams (concurrency case — known gap)

@slorber noted two diagrams entering the viewport at once can still race. To check that case:

  1. Put two Mermaid graph LR diagrams in the same tab, one above the other (no tabs).
  2. Reload the page and scroll so both enter the viewport in the same frame.
  3. Inspect both SVGs for arrow markers.

I have not claimed this PR fixes that concurrency case — only the hidden-tab render timing.

Status

  • Rework to a generalized fix per maintainer feedback
  • Remove useId() sanitization unless a concrete repro is shown (per inline review)

@meta-cla

meta-cla Bot commented Jul 13, 2026

Copy link
Copy Markdown

Hi @yoshibase!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@meta-cla meta-cla Bot added the CLA Signed Signed Facebook CLA label Jul 13, 2026
@meta-cla

meta-cla Bot commented Jul 13, 2026

Copy link
Copy Markdown

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@slorber slorber 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.

That doesn't pass our CI checks and also I don't think it's the correct generalized solution.

function useMermaidId(): string {
return useId();
// Mermaid marker IDs must be unique per diagram; sanitize React useId().
return useId().replace(/[^a-zA-Z0-9_-]/g, '');

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.

show me why we need this with a bug repro

if (!element) {
return undefined;
}
const observer = new IntersectionObserver(([entry]) => {

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.

Using an IntersectionObserver maybe works for tabs, but doesn't really this the concurrency problem described here: #8357 (comment)

We are looking for a general solution, not a solution that works only in some specific conditions.

2 mermaid diagrams rendered side-by-side and entering the viewport at the same time should not lead to a rendering bug

@slorber
slorber marked this pull request as draft July 16, 2026 08:51
@slorber slorber changed the title Mermaid lazy render when tab becomes visible fix(mermaid): Mermaid lazy render when tab becomes visible Jul 16, 2026
Lazy-render Mermaid diagrams when they enter the viewport so hidden tab
panels do not produce incomplete SVG markers. Fixes facebook#8357.
@yoshibase
yoshibase force-pushed the fix/issue-8357-mermaid-tabs branch from e996ddc to e076572 Compare July 16, 2026 23:47
@yoshibase

Copy link
Copy Markdown
Author

Thanks for the detailed review.

I've expanded the PR test plan with concrete repro steps for #8357 (tabs + DevTools SVG marker inspection) and noted the concurrency gap you pointed out. I'm reworking the implementation — the IntersectionObserver approach is too narrow and I don't have a solid repro for the useId() sanitization yet.

No change pushed to the code approach in this update; focusing on documenting repro/verification first while I investigate a generalized fix.

@yoshibase

Copy link
Copy Markdown
Author

Pausing this PR — IO approach does not fix concurrent-render case. Will revisit with render-queue or close.

@yoshibase

Copy link
Copy Markdown
Author

Closing — IntersectionObserver approach does not address the concurrent-render case discussed in review. Will revisit separately if I can land a render-queue fix.

@yoshibase yoshibase closed this Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed Signed Facebook CLA

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mermaid in tabs. The arrows are not displayed in the second tab

2 participants