The Mermaid component renders interactive diagrams from Mermaid syntax with built-in zoom and pan controls. It supports all Mermaid diagram types and automatically adapts to light/dark themes.
Usage
import { Mermaid } from '@mintlify/components';
<Mermaid
chart={`graph TD
A[Start] --> B{Is it working?}
B -->|Yes| C[Great!]
B -->|No| D[Debug]
D --> B`}
/>
Props
The Mermaid diagram definition string. Supports all Mermaid diagram types.
Additional CSS classes to apply to the container.
ariaLabel
string
default:"Mermaid diagram"
Accessible label for the diagram (for screen readers).
placement
'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
default:"bottom-right"
Position of the zoom and pan control buttons.
Whether to show the interactive controls. When undefined, controls are automatically shown when diagram height exceeds 120px. Set to true to always show controls, or false to always hide them.
Zoom and Pan Controls
The Mermaid component includes interactive controls for navigating large diagrams:
- Zoom In: Increase diagram size (magnification)
- Zoom Out: Decrease diagram size
- Pan Up/Down/Left/Right: Move the diagram viewport in any direction
- Reset View: Return to the original view (resets zoom and pan)
Control Layout
The controls are arranged in a 3×3 grid:
[ ] [↑] [+]
[←] [⟲] [→]
[ ] [↓] [-]
- Top row: Pan Up, Zoom In
- Middle row: Pan Left, Reset, Pan Right
- Bottom row: Pan Down, Zoom Out
Auto-Show Behavior
By default, controls are automatically shown when the diagram height is at least 120px. This prevents cluttering small diagrams with unnecessary controls.
Supported Diagram Types
The Mermaid component supports all standard Mermaid diagram types:
Flowchart
<Mermaid
chart={`graph TD
A[Start] --> B{Is it working?}
B -->|Yes| C[Great!]
B -->|No| D[Debug]
D --> B`}
/>
Sequence Diagram
<Mermaid
chart={`sequenceDiagram
participant Alice
participant Bob
Alice->>John: Hello John, how are you?
loop Healthcheck
John->>John: Fight against hypochondria
end
Note right of John: Rational thoughts prevail!
John-->>Alice: Great!
John->>Bob: How about you?
Bob-->>John: Jolly good!`}
/>
Class Diagram
<Mermaid
chart={`classDiagram
Animal <|-- Duck
Animal <|-- Fish
Animal : +int age
Animal : +String gender
Animal: +isMammal()
class Duck{
+String beakColor
+swim()
+quack()
}`}
/>
State Diagram
<Mermaid
chart={`stateDiagram-v2
[*] --> Still
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]`}
/>
Entity Relationship Diagram
<Mermaid
chart={`erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses`}
/>
Gantt Chart
<Mermaid
chart={`gantt
title A Gantt Diagram
dateFormat YYYY-MM-DD
section Section
A task :a1, 2024-01-01, 30d
Another task :after a1, 20d`}
/>
Pie Chart
<Mermaid
chart={`pie title Pets adopted by volunteers
"Dogs" : 386
"Cats" : 85
"Rats" : 15`}
/>
Git Graph
<Mermaid
chart={`gitGraph
commit
commit
branch develop
checkout develop
commit
commit
checkout main
merge develop
commit`}
/>
User Journey
<Mermaid
chart={`journey
title My working day
section Go to work
Make tea: 5: Me
Go upstairs: 3: Me
Do work: 1: Me, Cat
section Go home
Go downstairs: 5: Me
Sit down: 5: Me`}
/>
Examples
Basic Flowchart
<Mermaid
chart={`graph TD
A[Start] --> B{Is it working?}
B -->|Yes| C[Great!]
B -->|No| D[Debug]
D --> B`}
/>
Complex Architecture Diagram
<Mermaid
chart={`graph TB
subgraph Frontend
A[React App] --> B[Components]
B --> C[State Management]
end
subgraph Backend
D[API Gateway] --> E[Auth Service]
D --> F[Data Service]
E --> G[(Database)]
F --> G
end
A --> D`}
/>
Controls in Different Positions
{/* Top-left */}
<Mermaid
chart={`graph LR
A --> B --> C`}
placement="top-left"
actions={true}
/>
{/* Top-right */}
<Mermaid
chart={`graph LR
A --> B --> C`}
placement="top-right"
actions={true}
/>
{/* Bottom-left */}
<Mermaid
chart={`graph LR
A --> B --> C`}
placement="bottom-left"
actions={true}
/>
{/* Bottom-right (default) */}
<Mermaid
chart={`graph LR
A --> B --> C`}
placement="bottom-right"
actions={true}
/>
Force Show/Hide Controls
{/* Always show controls (even for small diagrams) */}
<Mermaid
chart={`flowchart LR
A --> B`}
actions={true}
/>
{/* Always hide controls (even for large diagrams) */}
<Mermaid
chart={`graph TD
A --> B --> C --> D --> E`}
actions={false}
/>
With Custom Styling
<Mermaid
chart={`graph LR
A[Start] --> B[End]`}
className="border rounded-lg p-4 bg-stone-50 dark:bg-stone-800"
/>
<div className="h-[600px] w-[800px]">
<Mermaid
chart={`graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[Car]
D --> G[Work]
E --> H[Fun]
F --> I[Travel]
G --> J[Success]
H --> J
I --> J`}
placement="top-right"
/>
</div>
Multiple Diagrams (with Unique IDs)
{/* The component automatically handles unique IDs to prevent SVG conflicts */}
<Mermaid
ariaLabel="Order processing diagram 1"
chart={`sequenceDiagram
participant Customer
participant API
Customer->>API: Create order
API-->>Customer: Order confirmed`}
/>
<Mermaid
ariaLabel="Order processing diagram 2"
chart={`sequenceDiagram
participant Customer
participant API
Customer->>API: Create order
API-->>Customer: Order confirmed`}
/>
Theme Support
The Mermaid component automatically adapts to your site’s theme:
- Light mode: Uses Mermaid’s
default theme
- Dark mode: Uses Mermaid’s
dark theme
- Font: Inherits from the parent container
Error Handling
If the diagram syntax is invalid, the component displays a user-friendly error message:
<Mermaid
chart={`graph TD
A[Start --> B{Invalid syntax here`}
/>
This will show:
Failed to render diagram
[Error message from Mermaid parser]
Technical Details
- Rendering: Diagrams are rendered off-screen first, then inserted into the DOM
- Unique IDs: Each diagram gets a unique ID to prevent SVG marker conflicts
- Marker ID Fix: SVG marker IDs are automatically made unique to support multiple diagrams
- Gantt Width: Gantt charts have a default width of 800px
- Re-rendering: Diagrams automatically re-render when the chart content or theme changes
Accessibility
- The diagram container has
role="img" for screen readers
- Custom
ariaLabel can be provided for better descriptions
- All control buttons have proper ARIA labels
- The control group has
aria-label="Diagram zoom and pan controls"
- Diagrams are rendered asynchronously to avoid blocking the UI
- Cancelled renders are properly cleaned up
- Resize observers automatically manage control visibility
usePanZoom Hook
For advanced use cases, you can use the usePanZoom hook directly to build custom zoom and pan interfaces.
Import
import { usePanZoom } from '@mintlify/components';
Hook API
The usePanZoom hook returns an object with the following properties:
CSS style object containing the transform properties for zoom and pan. Apply this to the element you want to transform.
Function to increase zoom level by the zoom step (0.15). Maximum zoom is 4x.
Function to decrease zoom level by the zoom step (0.15). Minimum zoom is 0.25x.
Function to reset zoom to 1x and pan to origin (0, 0).
pan
(dx: number, dy: number) => void
Function to pan the view by the specified pixel amounts. Positive values move right/down, negative values move left/up.
The default pan step size in pixels (50px). Use this value for consistent pan distances.
Hook Constants
The hook uses the following internal constants:
- MIN_SCALE:
0.25 - Minimum zoom level (25%)
- MAX_SCALE:
4 - Maximum zoom level (400%)
- ZOOM_STEP:
0.15 - Amount to zoom in/out per step
- PAN_STEP:
50 - Default pan distance in pixels
Custom Implementation Example
import { usePanZoom } from '@mintlify/components';
function CustomDiagram() {
const { style, zoomIn, zoomOut, reset, pan, panStep } = usePanZoom();
return (
<div className="relative h-96 overflow-hidden">
{/* Custom controls */}
<div className="absolute top-2 right-2 flex gap-2">
<button onClick={zoomIn}>+</button>
<button onClick={zoomOut}>-</button>
<button onClick={reset}>Reset</button>
<button onClick={() => pan(0, panStep)}>↑</button>
<button onClick={() => pan(0, -panStep)}>↓</button>
<button onClick={() => pan(panStep, 0)}>←</button>
<button onClick={() => pan(-panStep, 0)}>→</button>
</div>
{/* Your content with zoom/pan applied */}
<div style={style}>
<img src="/diagram.png" alt="Diagram" />
</div>
</div>
);
}
Advanced Usage with Keyboard Controls
import { usePanZoom } from '@mintlify/components';
import { useEffect } from 'react';
function KeyboardControlledDiagram() {
const { style, zoomIn, zoomOut, reset, pan, panStep } = usePanZoom();
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
switch (e.key) {
case '+':
case '=':
zoomIn();
break;
case '-':
case '_':
zoomOut();
break;
case '0':
reset();
break;
case 'ArrowUp':
pan(0, panStep);
break;
case 'ArrowDown':
pan(0, -panStep);
break;
case 'ArrowLeft':
pan(panStep, 0);
break;
case 'ArrowRight':
pan(-panStep, 0);
break;
}
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [zoomIn, zoomOut, reset, pan, panStep]);
return (
<div style={style}>
<YourContent />
</div>
);
}
ZoomControls Component
The ZoomControls component provides the interactive control panel used by the Mermaid component. You can use it independently for other zoomable content.
Import
import { ZoomControls } from '@mintlify/components';
Props
Callback function when zoom in button is clicked.
Callback function when zoom out button is clicked.
Callback function when reset button is clicked.
onPan
(dx: number, dy: number) => void
required
Callback function when pan buttons are clicked. Receives x and y delta values.
The distance in pixels to pan for each button click.
placement
'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
Position of the controls within the parent container. Defaults to "bottom-right".
Usage with usePanZoom
import { usePanZoom, ZoomControls } from '@mintlify/components';
function CustomZoomableContent() {
const { style, zoomIn, zoomOut, reset, pan, panStep } = usePanZoom();
return (
<div className="relative h-96 overflow-hidden">
<ZoomControls
onZoomIn={zoomIn}
onZoomOut={zoomOut}
onReset={reset}
onPan={pan}
panStep={panStep}
placement="top-right"
/>
<div style={style}>
<YourContent />
</div>
</div>
);
}
Source
View the source code:
- Mermaid:
packages/components/src/components/mermaid/mermaid.tsx:27
- usePanZoom Hook:
packages/components/src/components/mermaid/use-pan-zoom.ts:25
- Zoom Controls:
packages/components/src/components/mermaid/zoom-controls.tsx:43