All posts
MermaidInteractivityAdvanced

Interactive Mermaid diagrams: click events, navigation, and linking

6 min readThe MermaidCreator team

Static diagrams show structure; interactive ones tell stories. A Mermaid flowchart that links each step to documentation, a system architecture diagram where clicking a service shows logs, or a state machine that jumps to the handler code — these feel alive and guide users faster than a picture alone.

Mermaid's click events make this possible. Every node can trigger a link, open a URL, or call JavaScript. Let's build interactive diagrams.

Syntax: the click statement

The simplest click is a link. Add a click statement after your diagram:

flowchart TD
    A[Read the Docs]
    B{Understand?}
    C[Write Code]
    D[Debug]
    
    A --> B
    B -->|Yes| C
    B -->|No| A
    C --> D
    D --> B
    
    click A "https://docs.example.com"
    click C "https://github.com/me/repo"

When a user clicks node A, their browser navigates to the docs URL. Node C links to GitHub.

Syntax: click with tooltips

Combine click with a title attribute for hover tooltips:

flowchart LR
    api["API\n(click for logs)"]
    db[("Database")]
    cache[("Cache")]
    
    api --> db
    api --> cache
    
    click api "https://logs.example.com/api" "View API logs"
    click db "https://logs.example.com/db" "View DB logs"
    click cache "https://logs.example.com/cache" "View cache logs"

The third parameter becomes the tooltip text.

Advanced: JavaScript callbacks

For more control than simple links, use JavaScript callbacks. When a user clicks a node, Mermaid calls your handler:

<div id="diagram"></div>

<script>
  const diagram = `
    flowchart TD
      A[User Login]
      B[Verify Email]
      C[Set Password]
      D[Account Created]
      
      A --> B --> C --> D
      
      click A call handleStep
      click B call handleStep
      click C call handleStep
      click D call handleStep
  `;

  function handleStep(nodeId, e) {
    console.log(`Clicked node: ${nodeId}`);
    alert(`You clicked ${nodeId}`);
  }

  mermaid.initialize({ startOnLoad: true });
  mermaid.mermaidAPI.contentLoaded();
</script>

The call handleStep syntax invokes a global JavaScript function with the node ID. Use this for:

  • Logging and analytics — track which steps users explore
  • Modal dialogs — show details about a node without leaving the page
  • Dynamic updates — mark a node as "complete" and re-render
  • Deep linking — update the URL hash and restore diagram state

Real-world example: deployments pipeline

Build an interactive pipeline that shows status and links to logs:

flowchart LR
    commit["Commit Code"]
    test["Run Tests"]
    build["Build Docker Image"]
    stage["Deploy to Staging"]
    approve["Approval Gate"]
    prod["Deploy to Production"]
    
    commit --> test
    test --> build
    build --> stage
    stage --> approve
    approve --> prod
    
    click commit "https://github.com/me/repo/commits"
    click test "https://ci.example.com/jobs/test"
    click build "https://ci.example.com/jobs/build"
    click stage "https://staging.example.com/health"
    click prod "https://monitoring.example.com?env=prod"

Each step links to the tool responsible for that stage. No extra clicks to find the CI dashboard — it's one click away in the diagram.

Interactive microservices architecture

Show service status by color and link to dashboards:

<div id="diagram"></div>

<script>
  const services = {
    api: { status: 'healthy', dashboardUrl: 'https://dashboards.example.com/api' },
    auth: { status: 'healthy', dashboardUrl: 'https://dashboards.example.com/auth' },
    db: { status: 'slow', dashboardUrl: 'https://dashboards.example.com/db' },
  };

  const diagram = `
    flowchart LR
      subgraph Frontend
        web["Web App"]
      end
      
      subgraph Services
        api["API Gateway"]
        auth["Auth Service"]
      end
      
      subgraph Data
        db["Database"]
        cache["Cache"]
      end
      
      web --> api
      api --> auth
      auth --> db
      api --> cache
      
      click api call handleServiceClick
      click auth call handleServiceClick
      click db call handleServiceClick
  `;

  function handleServiceClick(nodeId, e) {
    const serviceName = nodeId.toLowerCase();
    const service = services[serviceName];
    
    if (service) {
      // Option 1: Navigate
      // window.location.href = service.dashboardUrl;
      
      // Option 2: Show a modal (requires a modal library)
      showModal(serviceName, service.status, service.dashboardUrl);
    }
  }

  function showModal(name, status, url) {
    const modal = document.createElement('div');
    modal.innerHTML = `
      <div style="padding: 20px; border: 1px solid #ccc; border-radius: 4px;">
        <h2>${name}</h2>
        <p>Status: <strong>${status}</strong></p>
        <a href="${url}" target="_blank">Open Dashboard</a>
        <button onclick="this.closest('div').remove()">Close</button>
      </div>
    `;
    document.body.appendChild(modal);
  }

  mermaid.initialize({ startOnLoad: true });
  mermaid.mermaidAPI.contentLoaded();
</script>

Now clicking a service shows its status and a link to its dashboard — all without leaving the diagram.

Sequence diagrams with documentation links

Sequence diagrams benefit from interactivity too. They use the link directive (not click) to attach a documentation menu to each participant — link <actor>: <Label> @ <url>:

sequenceDiagram
    participant C as Client
    participant A as API
    participant Auth as Auth Service
    participant DB as Database
    
    C->>A: POST /login
    A->>Auth: Verify credentials
    Auth->>DB: Query user
    DB-->>Auth: User record
    Auth-->>A: Token
    A-->>C: 200 OK { token }
    
    link C: Docs @ https://docs.example.com/client-api
    link A: Docs @ https://docs.example.com/api-endpoints
    link Auth: Docs @ https://docs.example.com/auth-service
    link DB: Docs @ https://docs.example.com/database

Reviewers or new team members can explore the flow and jump to each component's documentation.

Tips for effective interactive diagrams

1. Provide visual feedback

Use CSS or Mermaid theming to show which nodes are clickable. Add a subtle "cursor: pointer" or highlight on hover:

<style>
  .mermaid g[data-node-id] { cursor: pointer; }
  .mermaid g[data-node-id]:hover rect { fill: #f0f0f0; }
</style>

2. Don't hide critical information behind clicks

Interactive diagrams are great for exploration, but the core message should be obvious without clicking. If users need to click every node to understand the flow, the diagram is doing too much.

3. Use consistent link targets

If all API steps link to your API docs, users build a mental model: "click any step to see its docs." Consistency breeds trust.

4. Test on mobile

Click events work on touch, but diagrams can be cramped on phones. Test on a real device to ensure nodes are large enough to tap comfortably.

Integration with React and Vue

If you're building a web app with React or Vue, wrap Mermaid diagrams in a component and manage click handlers at the app level:

React example:

function InteractiveDiagram({ data }) {
  const handleNodeClick = (nodeId) => {
    const service = data[nodeId];
    // navigate, show modal, etc.
    navigate(`/services/${nodeId}`);
  };

  useEffect(() => {
    window.handleNodeClick = handleNodeClick;
    mermaid.mermaidAPI.contentLoaded();
  }, [data]);

  return (
    <div className="mermaid">
      {diagramDefinition}
    </div>
  );
}

Vue example:

<template>
  <div class="mermaid" v-html="diagramDefinition"></div>
</template>

<script>
export default {
  props: ['diagramDefinition'],
  mounted() {
    window.handleNodeClick = (nodeId) => {
      this.$router.push(`/services/${nodeId}`);
    };
    mermaid.mermaidAPI.contentLoaded();
  }
};
</script>

Comparison: interactive vs. static

TypeBest forDrawback
Static diagramBlog posts, documentation, printed materialsRequires separate tools/links for exploration
Interactive with linksDashboards, internal docs, onboardingLinks can rot if URLs change
Interactive with JS callbacksReal-time status, complex dashboardsRequires JavaScript and build tooling

Most teams start with static, add click-to-link for important diagrams, and use callbacks only for dashboards that update frequently.

FAQ

Q: Can I change node color on click? A: Yes, via JavaScript. Click the node, then re-render the diagram with updated styling. Mermaid themes are configurable, so you can update the theme based on state.

Q: Do interactive diagrams work in GitHub markdown? A: Click links do, but JavaScript callbacks don't (GitHub's markdown renderer doesn't execute scripts). Use click with URLs for README diagrams.

Q: Can I track which nodes users click? A: Yes. In your click handler, send an analytics event: analytics.track('diagram_click', { nodeId, diagram: 'architecture' }).

Q: How do I link to an anchor on the same page? A: Use a relative URL: click A "#deployment-guide". The browser will scroll to that anchor.

Interactive diagrams turn passive documentation into active learning tools. Start with simple links, then add callbacks as your use case demands. Try building an interactive dashboard diagram in the editor — the visual and code panes stay in sync as you refine the structure.

Related posts