Skip to content

feat: Mermaid diagram rendering in chat bubbles & improved streaming reliability#30

Merged
OpenSource03 merged 8 commits intomasterfrom
claude/add-mermaid-rendering-chat-bubbles
Mar 15, 2026
Merged

feat: Mermaid diagram rendering in chat bubbles & improved streaming reliability#30
OpenSource03 merged 8 commits intomasterfrom
claude/add-mermaid-rendering-chat-bubbles

Conversation

@Claude
Copy link
Contributor

@Claude Claude AI commented Mar 14, 2026

Summary

  • Adds native Mermaid diagram rendering for code blocks tagged with language-mermaid
  • Diagrams render as interactive SVG instead of syntax-highlighted text
  • Includes error handling with fallback to raw code display

Type of Change

  • ✨ New feature (non-breaking change that adds functionality)
  • 🎨 UI / design improvement
  • 🧪 Tests / CI

Related Issues

Closes #178

How to Test

  1. Start a chat session with any engine
  2. Ask Claude to generate a Mermaid diagram (e.g., "Create a flowchart showing user authentication")
  3. Verify the diagram renders as an interactive SVG instead of text
  4. Hover over the diagram header to verify the copy button appears
  5. Test error handling by sending invalid Mermaid syntax (e.g., graph TD\nA[-->)

Example Mermaid code block:

```mermaid
graph TD
    A[Start] --> B{Is User Logged In?}
    B -->|Yes| C[Show Dashboard]
    B -->|No| D[Redirect to Login]
```

Screenshots / Screen Recording

Will be added by reviewer

Checklist

  • I've tested this on macOS (required for Electron/native features)
  • TypeScript compiles with no errors (pnpm build)
  • No any types introduced
  • Logical margins used (ms-*/me-* instead of ml-*/mr-*)
  • User-generated content containers have wrap-break-word
  • New shared types go in shared/types/, not src/types/
  • Large components/hooks are decomposed into sub-components/sub-hooks if needed
Original prompt

This section details on the original issue you should resolve

<issue_title>[Feature]: Mermaid rendering in chat bubbles</issue_title>
<issue_description>### Problem / Motivation

It would be nice if mermaid diagrams were rendered in the chat bubbles. Cursor does it and it is one of the few features that I miss when using coding agent TUIs.

Proposed Solution

When rendering code blocks, if a mermaid block is detected, use mermaid to render it instead of just doing syntax highlighting.

Alternatives Considered

No response

Area

Chat / Messaging

Relevant Engine

All engines

How important is this to you?

Would significantly improve my workflow

Contribution

  • I'd be willing to submit a PR for this feature

Additional Context

No response</issue_description>

Comments on the Issue (you are @claude[agent] in this section)

Claude AI and others added 2 commits March 14, 2026 17:12
Co-authored-by: OpenSource03 <29690431+OpenSource03@users.noreply.github.com>
Co-authored-by: OpenSource03 <29690431+OpenSource03@users.noreply.github.com>
@Claude Claude AI changed the title [WIP] [Feature] Add mermaid rendering in chat bubbles feat: Mermaid diagram rendering in chat bubbles Mar 14, 2026
@Claude Claude AI requested a review from OpenSource03 March 14, 2026 17:15
@OpenSource03 OpenSource03 marked this pull request as ready for review March 15, 2026 21:41
@OpenSource03 OpenSource03 requested a review from Copilot March 15, 2026 21:41
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee2c60eee2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}, []);

useEffect(() => {
if (!containerRef.current) return;

Choose a reason for hiding this comment

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

P1 Badge Re-render diagrams after an initial parse failure

After mermaid.render() throws once, the component switches to the error branch, which does not render the element attached to containerRef; on later code updates (for example while assistant output is still streaming), this early return prevents setError(null) and mermaid.render() from running again, so the diagram stays stuck in the error fallback even when the Mermaid source becomes valid.

Useful? React with 👍 / 👎.

mermaid.initialize({
startOnLoad: false,
theme: "dark",
securityLevel: "loose",

Choose a reason for hiding this comment

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

P1 Badge Use strict Mermaid security for untrusted chat content

This initializes Mermaid with securityLevel: "loose" even though diagram text comes from model/user-generated chat content and is later injected as raw SVG; in this mode Mermaid permits less-restricted markup/link behavior, which can allow malicious diagram payloads to inject active content into the renderer context where privileged IPC bridges are exposed.

Useful? React with 👍 / 👎.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds native Mermaid diagram rendering inside chat bubbles by detecting ```mermaid fenced code blocks and rendering them as SVG instead of syntax-highlighted text.

Changes:

  • Detect language-mermaid code fences in MessageBubble and render via a dedicated MermaidDiagram component.
  • Introduce MermaidDiagram component with header + copy button and an error fallback to raw code.
  • Add Mermaid dependency and basic component tests.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/components/MessageBubble.tsx Routes mermaid fenced code blocks to the new Mermaid renderer instead of syntax highlighting.
src/components/MermaidDiagram.tsx New component that initializes Mermaid and injects rendered SVG with an error fallback UI.
src/components/MermaidDiagram.test.tsx New tests asserting basic structure for the Mermaid component.
package.json Adds mermaid dependency.
pnpm-lock.yaml Locks Mermaid and its transitive dependencies.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +34 to +38
async function renderDiagram() {
try {
setError(null);
const { svg: renderedSvg } = await mermaid.render(id, code);
setSvg(renderedSvg);
Comment on lines +30 to +45

// Generate unique ID for this diagram
const id = `mermaid-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;

async function renderDiagram() {
try {
setError(null);
const { svg: renderedSvg } = await mermaid.render(id, code);
setSvg(renderedSvg);
} catch (err) {
console.error("Mermaid rendering error:", err);
setError(err instanceof Error ? err.message : "Failed to render diagram");
}
}

void renderDiagram();
Comment on lines 18 to +21
import { ThinkingBlock } from "./ThinkingBlock";
import { CopyButton } from "./CopyButton";
import { ImageLightbox } from "./ImageLightbox";
import { MermaidDiagram } from "./MermaidDiagram";
Comment on lines +19 to +24
mermaid.initialize({
startOnLoad: false,
theme: "dark",
securityLevel: "loose",
});
mermaidInitialized = true;
OpenSource03 and others added 2 commits March 15, 2026 22:47
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 14a0be555d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +23 to +24
if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
return "dark";

Choose a reason for hiding this comment

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

P1 Badge Respect explicit light mode when resolving Mermaid theme

This theme resolver treats any non-dark root class as a signal to fall back to OS preference, so when a user explicitly selects light mode on a dark OS, Mermaid diagrams still render with the dark theme and can keep following OS theme changes. In this app, explicit theme choice is represented by the <html> class (dark present/absent), so using matchMedia here overrides user intent for light mode.

Useful? React with 👍 / 👎.

@OpenSource03 OpenSource03 changed the title feat: Mermaid diagram rendering in chat bubbles feat: Mermaid diagram rendering in chat bubbles & improved streaming reliability Mar 15, 2026
OpenSource03 and others added 3 commits March 16, 2026 00:45
Four targeted fixes for intermittent markdown rendering failures:

1. streaming-buffer: Replace mergeStreamingChunk overlap detection with
   simple concatenation for text deltas — the SDK sends pure incremental
   chunks, and the overlap heuristics produced false positives that ate
   markdown characters (|, `, \n, -) at token boundaries

2. useClaude: Capture buffer.current.messageId before queueing the
   assistant event's setMessages updater — message_stop could clear it
   via resetStreaming() before React processed the updater, silently
   dropping the authoritative final content snapshot

3. useStreamingTextReveal: Extend DOM surgery guards from CODE/PRE to
   include TABLE, UL, OL, BLOCKQUOTE, DL and descendants — prevents
   text-node splitting inside structurally volatile elements that can
   desync React's reconciler

4. MessageBubble: Remove IntersectionObserver lazy rendering gate —
   messages loaded from persistence or background store mounted with
   isVisible=false and the observer didn't fire reliably inside Radix
   ScrollArea, leaving content as plain text with literal # and *

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@OpenSource03 OpenSource03 merged commit 6b2153a into master Mar 15, 2026
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0c0d31bebe

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const language = match[1];

// Render mermaid diagrams with MermaidDiagram component
if (language === "mermaid") {

Choose a reason for hiding this comment

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

P2 Badge Normalize Mermaid language tag before renderer dispatch

The Mermaid branch only runs when language === "mermaid", but markdown info strings are case-preserving, so fences like Mermaid or MERMAID produce language-Mermaid and fall back to plain syntax highlighting instead of diagram rendering. This makes Mermaid support inconsistent for equivalent tags and is easy to hit with model-generated markdown that capitalizes language names.

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Mermaid rendering in chat bubbles

3 participants