While there are a few Mermaid components out there, I wanted one that would let users click on diagram elements and have that interaction available in Python. This makes it possible to build apps where clicking a node in a flowchart triggers a query, updates another widget, or navigates to more detail.
Basic Usage
import streamlit as st
from streamlit_mermaid_interactive import mermaid
flowchart_code = """
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[OK]
B -->|No| D[End]
"""
result = mermaid(flowchart_code, theme="neutral", key="flowchart")
if result.get("entity_clicked"):
st.info(f"Clicked: {result['entity_clicked']}")
Supported Diagram Types
Fully Interactive (click events work):
Flowcharts
Sequence Diagrams
Entity Relationship Diagrams (ERD)
State Diagrams
Class Diagrams
Rendered but not yet clickable:
Pie Chart, Gantt, Git Graph, User Journey, Timeline
(PRs welcome if anyone wants to tackle click detection for those!)
Themes
Supports "neutral" (default), "dark", "forest", and "base".
Let me know if you run into issues or have feature requests!
Welcome to the Streamlit community and thanks for sharing your new component! The streamlit-mermaid-interactive component allows you to render Mermaid diagrams in Streamlit and capture click events on diagram entities, making it possible to build interactive apps that respond to user actions on diagrams. You can install it with pip install streamlit-mermaid-interactive and use it as shown in your example to detect clicks and update your app accordingly.
This approach aligns with best practices for custom Streamlit components, leveraging the ability to pass data and events between JavaScript and Python, as described in the Streamlit Components documentation and API reference. Your component extends the interactivity of Mermaid diagrams beyond what’s available in existing solutions, and your use of themes and support for multiple diagram types is a great touch. Community members can check out your demo app and GitHub repo for more details.
import streamlit as st
def show_readme(filepath='README.md'):
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
# Split content to handle mermaid blocks specifically
parts = content.split("```mermaid")
st.markdown(parts[0])
for part in parts[1:]:
if "```" in part:
mermaid_code, remaining = part.split("```", 1)
# Use st.components or a specific mermaid renderer
# Standard Streamlit doesn't have a native 'st.mermaid' but many use:
import streamlit.components.v1 as components
html_code = f"""
<pre class="mermaid">
{mermaid_code}
</pre>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({{ startOnLoad: true }});
</script>
"""
components.html(html_code, height=400, scrolling=True)
st.markdown(remaining)
else:
st.markdown("```mermaid" + part)
except FileNotFoundError:
st.error(f"Error: {filepath} not found.")