mirror of
https://github.com/supabase/supabase.git
synced 2026-10-12 12:55:06 +03:00
Add new Mermaid diagram examples and improve docs
Introduces new example components for basic, subgraph flowchart, simple ER, and API sequence Mermaid diagrams. Updates the documentation to provide clearer usage instructions, more examples, and improved structure. Refactors the Mermaid component to enhance zoom functionality, removes custom SVG message backgrounds, and adds a dedicated CSS file for zoom overlay theming.
This commit is contained in:
1 parent
b89b1d2b16
commit
fcc4fef2c3
10 files changed
+276
-139
No files matched your search
@@ -2601,13 +2601,46 @@ export const Index: Record<string, any> = {
|
||||
subcategory: "undefined",
|
||||
chunks: []
|
||||
},
|
||||
"mermaid-styling": {
|
||||
name: "mermaid-styling",
|
||||
"mermaid-flowchart-subgraph": {
|
||||
name: "mermaid-flowchart-subgraph",
|
||||
type: "components:example",
|
||||
registryDependencies: ["mermaid"],
|
||||
component: React.lazy(() => import("@/registry/default/example/mermaid-styling")),
|
||||
component: React.lazy(() => import("@/registry/default/example/mermaid-flowchart-subgraph")),
|
||||
source: "",
|
||||
files: ["registry/default/example/mermaid-styling.tsx"],
|
||||
files: ["registry/default/example/mermaid-flowchart-subgraph.tsx"],
|
||||
category: "undefined",
|
||||
subcategory: "undefined",
|
||||
chunks: []
|
||||
},
|
||||
"mermaid-sequence-api": {
|
||||
name: "mermaid-sequence-api",
|
||||
type: "components:example",
|
||||
registryDependencies: ["mermaid"],
|
||||
component: React.lazy(() => import("@/registry/default/example/mermaid-sequence-api")),
|
||||
source: "",
|
||||
files: ["registry/default/example/mermaid-sequence-api.tsx"],
|
||||
category: "undefined",
|
||||
subcategory: "undefined",
|
||||
chunks: []
|
||||
},
|
||||
"mermaid-er-simple": {
|
||||
name: "mermaid-er-simple",
|
||||
type: "components:example",
|
||||
registryDependencies: ["mermaid"],
|
||||
component: React.lazy(() => import("@/registry/default/example/mermaid-er-simple")),
|
||||
source: "",
|
||||
files: ["registry/default/example/mermaid-er-simple.tsx"],
|
||||
category: "undefined",
|
||||
subcategory: "undefined",
|
||||
chunks: []
|
||||
},
|
||||
"mermaid-basic": {
|
||||
name: "mermaid-basic",
|
||||
type: "components:example",
|
||||
registryDependencies: ["mermaid"],
|
||||
component: React.lazy(() => import("@/registry/default/example/mermaid-basic")),
|
||||
source: "",
|
||||
files: ["registry/default/example/mermaid-basic.tsx"],
|
||||
category: "undefined",
|
||||
subcategory: "undefined",
|
||||
chunks: []
|
||||
|
||||
@@ -4,85 +4,123 @@ description: Render diagrams from text using Mermaid syntax.
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentPreview name="mermaid-demo" peekCode wide />
|
||||
|
||||
## Installation
|
||||
|
||||
The Mermaid component is available from the `ui` package:
|
||||
|
||||
```tsx
|
||||
import { Mermaid } from 'ui'
|
||||
```
|
||||
<ComponentPreview name="mermaid-basic" peekCode wide />
|
||||
|
||||
## Usage
|
||||
|
||||
### In MDX (Blog Posts)
|
||||
|
||||
The simplest way to add diagrams in blog posts is with a fenced code block using the `mermaid` language tag:
|
||||
|
||||
````mdx
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[User Request] --> B{Authenticated?}
|
||||
B -->|Yes| C[Process Request]
|
||||
B -->|No| D[Return 401]
|
||||
```
|
||||
````
|
||||
|
||||
This is automatically rendered as a diagram. No imports needed.
|
||||
|
||||
### As a Component
|
||||
|
||||
For more control (custom className, disabling zoom), import and use the component directly:
|
||||
|
||||
```tsx
|
||||
import { Mermaid } from 'ui'
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Mermaid
|
||||
chart={`
|
||||
graph TD
|
||||
A[Start] --> B[End]
|
||||
export function MyDiagram() {
|
||||
return (
|
||||
<Mermaid
|
||||
chart={`
|
||||
flowchart LR
|
||||
A[User Request] --> B{Authenticated?}
|
||||
B -->|Yes| C[Process Request]
|
||||
B -->|No| D[Return 401]
|
||||
`}
|
||||
/>
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
Use the component when you need to pass props like `className` or `zoomable`, conditionally render, or integrate with React logic.
|
||||
|
||||
### Supabase Architecture
|
||||
## Flowcharts
|
||||
|
||||
<ComponentPreview name="mermaid-demo" />
|
||||
Use `flowchart` or `graph` to create flowcharts with nodes and edges. Supports decision diamonds, different node shapes, and directional layouts (TD, LR, etc).
|
||||
[View Mermaid flowchart docs](https://mermaid.js.org/syntax/flowchart.html)
|
||||
|
||||
---
|
||||
|
||||
### Flowchart
|
||||
A basic request flow showing conditional branching with a decision node (`{}`), demonstrating how to visualize auth checks and data flow.
|
||||
|
||||
<ComponentPreview name="mermaid-flowchart" />
|
||||
|
||||
---
|
||||
### With Subgraphs
|
||||
|
||||
### ER Diagram
|
||||
Group related nodes into labeled subgraphs to show system boundaries. Useful for depicting frontend/backend separation or microservice architecture.
|
||||
|
||||
<ComponentPreview name="mermaid-er-diagram" />
|
||||
<ComponentPreview name="mermaid-flowchart-subgraph" />
|
||||
|
||||
---
|
||||
### Supabase Architecture
|
||||
|
||||
### Async Streaming (FDW)
|
||||
Shows how client requests flow through the API Gateway to core services (Auth, PostgREST, Realtime) which all connect to PostgreSQL.
|
||||
|
||||
<ComponentPreview name="mermaid-sequence-async" />
|
||||
|
||||
---
|
||||
|
||||
### Sync Blocking (FDW)
|
||||
|
||||
<ComponentPreview name="mermaid-sequence-sync" />
|
||||
|
||||
---
|
||||
<ComponentPreview name="mermaid-demo" />
|
||||
|
||||
### OAuth Authorization Flow
|
||||
|
||||
Illustrates the OAuth 2.0 authorization code flow, showing the handoff between a third-party app, your authorization endpoint, and Supabase Auth for token exchange.
|
||||
|
||||
<ComponentPreview name="mermaid-oauth-flow" />
|
||||
|
||||
## ER Diagrams
|
||||
|
||||
Use `erDiagram` to create entity-relationship diagrams showing database schemas. Great for documenting table relationships and foreign keys.
|
||||
[View Mermaid ER diagram docs](https://mermaid.js.org/syntax/entityRelationshipDiagram.html)
|
||||
|
||||
A simple e-commerce schema showing cardinality between customers, orders, products, and line items using crow's foot notation.
|
||||
|
||||
<ComponentPreview name="mermaid-er-simple" />
|
||||
|
||||
### With Attributes
|
||||
|
||||
Include column definitions with types and constraints (PK, FK) to create more detailed schema documentation.
|
||||
|
||||
<ComponentPreview name="mermaid-er-diagram" />
|
||||
|
||||
## Sequence Diagrams
|
||||
|
||||
Use `sequenceDiagram` to show interactions between participants over time. Ideal for documenting API flows, authentication handshakes, or any request/response patterns.
|
||||
[View Mermaid sequence diagram docs](https://mermaid.js.org/syntax/sequenceDiagram.html)
|
||||
|
||||
A typical authenticated API request showing JWT validation, database insert, and response flow between Client, API, Auth, and DB participants.
|
||||
|
||||
<ComponentPreview name="mermaid-sequence-api" />
|
||||
|
||||
### Async Streaming (FDW)
|
||||
|
||||
Shows how Foreign Data Wrappers can stream data asynchronously using bounded channels, with parallel execution indicated by the `par` block.
|
||||
|
||||
<ComponentPreview name="mermaid-sequence-async" />
|
||||
|
||||
### Sync Blocking (FDW)
|
||||
|
||||
Contrasts with async by showing traditional blocking FDW behavior where all rows are fetched and buffered before processing.
|
||||
|
||||
<ComponentPreview name="mermaid-sequence-sync" />
|
||||
|
||||
## Props
|
||||
|
||||
| Prop | Type | Description |
|
||||
| ----------- | -------- | ------------------------------------ |
|
||||
| `chart` | `string` | The Mermaid diagram definition |
|
||||
| `className` | `string` | Optional CSS class for the container |
|
||||
| Prop | Type | Default | Description |
|
||||
| ----------- | --------- | ------- | ------------------------------------ |
|
||||
| `chart` | `string` | — | The Mermaid diagram definition |
|
||||
| `className` | `string` | — | Optional CSS class for the container |
|
||||
| `zoomable` | `boolean` | `true` | Enable click-to-zoom on the diagram |
|
||||
|
||||
## Supported Diagram Types
|
||||
## Learn More
|
||||
|
||||
Mermaid supports many diagram types including:
|
||||
See the [Mermaid documentation](https://mermaid.js.org/intro/) for full syntax reference and additional diagram types.
|
||||
|
||||
- **Flowcharts** - `flowchart` or `graph`
|
||||
- **Sequence Diagrams** - `sequenceDiagram`
|
||||
- **Class Diagrams** - `classDiagram`
|
||||
- **State Diagrams** - `stateDiagram-v2`
|
||||
- **ER Diagrams** - `erDiagram`
|
||||
- **Gantt Charts** - `gantt`
|
||||
- **Pie Charts** - `pie`
|
||||
- **Git Graphs** - `gitGraph`
|
||||
```
|
||||
|
||||
See the [Mermaid documentation](https://mermaid.js.org/intro/) for full syntax reference.
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Mermaid } from 'ui'
|
||||
|
||||
export default function MermaidBasic() {
|
||||
return (
|
||||
<Mermaid
|
||||
chart={`
|
||||
flowchart TD
|
||||
A[Start] --> B{Is it working?}
|
||||
B -->|Yes| C[Great!]
|
||||
B -->|No| D[Debug]
|
||||
D --> B
|
||||
C --> E[End]
|
||||
`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -5,45 +5,25 @@ export default function MermaidDemo() {
|
||||
<Mermaid
|
||||
chart={`
|
||||
flowchart TB
|
||||
subgraph Client
|
||||
App[Your Application]
|
||||
end
|
||||
Client[Your Application]
|
||||
|
||||
|
||||
Gateway[API Gateway]
|
||||
Auth[Auth]
|
||||
API[PostgREST]
|
||||
Realtime[Realtime]
|
||||
PgBouncer[PgBouncer]
|
||||
Postgres[(PostgreSQL)]
|
||||
|
||||
subgraph Gateway
|
||||
Kong[Kong API Gateway]
|
||||
end
|
||||
|
||||
subgraph Services
|
||||
Auth[GoTrue<br/>Auth]
|
||||
API[PostgREST<br/>REST API]
|
||||
Realtime[Realtime<br/>WebSockets]
|
||||
Storage[Storage API<br/>S3-compatible]
|
||||
Meta[postgres-meta<br/>DB Management]
|
||||
Functions[Deno<br/>Edge Functions]
|
||||
GraphQL[pg_graphql<br/>GraphQL]
|
||||
end
|
||||
|
||||
subgraph Data
|
||||
Postgres[(PostgreSQL)]
|
||||
Supavisor[Supavisor<br/>Connection Pooler]
|
||||
end
|
||||
|
||||
App --> Kong
|
||||
Kong --> Auth
|
||||
Kong --> API
|
||||
Kong --> Realtime
|
||||
Kong --> Storage
|
||||
Kong --> Meta
|
||||
Kong --> Functions
|
||||
Kong --> GraphQL
|
||||
|
||||
Auth --> Supavisor
|
||||
API --> Supavisor
|
||||
Realtime --> Supavisor
|
||||
Storage --> Supavisor
|
||||
Meta --> Supavisor
|
||||
GraphQL --> Supavisor
|
||||
Supavisor --> Postgres
|
||||
Client --> Gateway
|
||||
Client --> PgBouncer
|
||||
Client <--> Realtime
|
||||
Gateway --> Auth
|
||||
Gateway --> API
|
||||
Auth --> Postgres
|
||||
API --> Postgres
|
||||
Realtime <--> Postgres
|
||||
PgBouncer --> Postgres
|
||||
`}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Mermaid } from 'ui'
|
||||
|
||||
export default function MermaidErSimple() {
|
||||
return (
|
||||
<Mermaid
|
||||
chart={`
|
||||
erDiagram
|
||||
CUSTOMER ||--o{ ORDER : places
|
||||
ORDER ||--|{ LINE_ITEM : contains
|
||||
PRODUCT ||--o{ LINE_ITEM : "ordered in"
|
||||
`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Mermaid } from 'ui'
|
||||
|
||||
export default function MermaidFlowchartSubgraph() {
|
||||
return (
|
||||
<Mermaid
|
||||
chart={`
|
||||
flowchart LR
|
||||
subgraph Frontend
|
||||
A[React App] --> B[API Client]
|
||||
end
|
||||
|
||||
subgraph Backend
|
||||
C[Edge Functions] --> D[Database]
|
||||
C --> E[Storage]
|
||||
end
|
||||
|
||||
B --> C
|
||||
`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Mermaid } from 'ui'
|
||||
|
||||
export default function MermaidSequenceApi() {
|
||||
return (
|
||||
<Mermaid
|
||||
chart={`
|
||||
sequenceDiagram
|
||||
participant Client
|
||||
participant API
|
||||
participant Auth
|
||||
participant DB
|
||||
|
||||
Client->>API: POST /api/data
|
||||
API->>Auth: Validate JWT
|
||||
Auth-->>API: Token valid
|
||||
API->>DB: INSERT query
|
||||
DB-->>API: Success
|
||||
API-->>Client: 201 Created
|
||||
`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -1389,4 +1389,28 @@ export const examples: Registry = [
|
||||
registryDependencies: ['mermaid'],
|
||||
files: ['example/mermaid-oauth-flow.tsx'],
|
||||
},
|
||||
{
|
||||
name: 'mermaid-flowchart-subgraph',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['mermaid'],
|
||||
files: ['example/mermaid-flowchart-subgraph.tsx'],
|
||||
},
|
||||
{
|
||||
name: 'mermaid-sequence-api',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['mermaid'],
|
||||
files: ['example/mermaid-sequence-api.tsx'],
|
||||
},
|
||||
{
|
||||
name: 'mermaid-er-simple',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['mermaid'],
|
||||
files: ['example/mermaid-er-simple.tsx'],
|
||||
},
|
||||
{
|
||||
name: 'mermaid-basic',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['mermaid'],
|
||||
files: ['example/mermaid-basic.tsx'],
|
||||
},
|
||||
]
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import 'react-medium-image-zoom/dist/styles.css'
|
||||
import './mermaid-zoom.css'
|
||||
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import mermaid from 'mermaid'
|
||||
@@ -42,7 +43,6 @@ const darkThemeVariables = {
|
||||
clusterBorder: '#404040',
|
||||
defaultLinkColor: '#3ecf8e',
|
||||
edgeLabelBackground: '#171717',
|
||||
// ER diagram specific
|
||||
attributeBackgroundColorOdd: '#262626',
|
||||
attributeBackgroundColorEven: '#171717',
|
||||
rowOdd: '#262626',
|
||||
@@ -85,7 +85,6 @@ const lightThemeVariables = {
|
||||
clusterBorder: '#e5e5e5',
|
||||
defaultLinkColor: '#3ecf8e',
|
||||
edgeLabelBackground: '#ffffff',
|
||||
// ER diagram specific
|
||||
attributeBackgroundColorOdd: '#f5f5f5',
|
||||
attributeBackgroundColorEven: '#ffffff',
|
||||
rowOdd: '#f5f5f5',
|
||||
@@ -129,6 +128,7 @@ export function Mermaid({ chart, className, zoomable = true }: MermaidProps) {
|
||||
},
|
||||
flowchart: {
|
||||
useMaxWidth: false,
|
||||
curve: 'linear',
|
||||
},
|
||||
er: {
|
||||
useMaxWidth: false,
|
||||
@@ -197,36 +197,6 @@ export function Mermaid({ chart, className, zoomable = true }: MermaidProps) {
|
||||
rect.setAttribute('stroke', isPostgres ? '#336791' : isDark ? '#525252' : '#d4d4d4')
|
||||
})
|
||||
|
||||
// Add pill backgrounds to message text (skip notes - they already have backgrounds)
|
||||
const messageTexts = doc.querySelectorAll('.messageText')
|
||||
messageTexts.forEach((text) => {
|
||||
// Skip if there's already a sibling rect (notes have background rects)
|
||||
const parent = text.parentElement
|
||||
if (parent?.querySelector('rect')) return
|
||||
|
||||
const x = parseFloat(text.getAttribute('x') || '0')
|
||||
const y = parseFloat(text.getAttribute('y') || '0')
|
||||
const dy = text.getAttribute('dy')
|
||||
// Parse dy (e.g., "1em" -> 16px)
|
||||
const dyOffset = dy ? parseFloat(dy) * 16 : 0
|
||||
|
||||
const textContent = text.textContent || ''
|
||||
const estimatedWidth = textContent.length * 9
|
||||
const height = 28
|
||||
const paddingX = 16
|
||||
|
||||
const rect = doc.createElementNS('http://www.w3.org/2000/svg', 'rect')
|
||||
rect.setAttribute('x', String(x - estimatedWidth / 2 - paddingX))
|
||||
rect.setAttribute('y', String(y + dyOffset - height / 2))
|
||||
rect.setAttribute('width', String(estimatedWidth + paddingX * 2))
|
||||
rect.setAttribute('height', String(height))
|
||||
rect.setAttribute('rx', '14')
|
||||
rect.setAttribute('fill', isDark ? '#262626' : '#f5f5f5')
|
||||
rect.setAttribute('class', 'messageTextBg')
|
||||
|
||||
text.parentNode?.insertBefore(rect, text)
|
||||
})
|
||||
|
||||
const serializer = new XMLSerializer()
|
||||
const processedSvg = serializer.serializeToString(doc)
|
||||
setSvg(processedSvg)
|
||||
@@ -258,23 +228,29 @@ export function Mermaid({ chart, className, zoomable = true }: MermaidProps) {
|
||||
)
|
||||
}
|
||||
|
||||
const content = (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={cn(
|
||||
'my-6 flex justify-center rounded-lg border p-6 pb-8',
|
||||
isDark ? 'bg-[#171717] border-[#333]' : 'bg-white border-[#e5e5e5]',
|
||||
'[&_svg]:h-auto [&_svg]:max-w-full',
|
||||
zoomable && 'cursor-zoom-in',
|
||||
className
|
||||
)}
|
||||
dangerouslySetInnerHTML={{ __html: svg }}
|
||||
/>
|
||||
const containerClassName = cn(
|
||||
'my-6 flex justify-center rounded-lg border p-6 pb-8',
|
||||
isDark ? 'bg-[#171717] border-[#333]' : 'bg-white border-[#e5e5e5]',
|
||||
className
|
||||
)
|
||||
|
||||
if (zoomable) {
|
||||
return <Zoom zoomMargin={40}>{content}</Zoom>
|
||||
// Convert SVG to data URL for react-medium-image-zoom compatibility
|
||||
const svgDataUrl = `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(svg)))}`
|
||||
return (
|
||||
<div ref={containerRef} className={containerClassName}>
|
||||
<Zoom zoomMargin={40}>
|
||||
<img src={svgDataUrl} alt="Mermaid diagram" className="h-auto max-w-full" />
|
||||
</Zoom>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return content
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={cn(containerClassName, '[&_svg]:h-auto [&_svg]:max-w-full')}
|
||||
dangerouslySetInnerHTML={{ __html: svg }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
@tailwind utilities;
|
||||
|
||||
@layer utilities {
|
||||
[data-rmiz-modal-overlay='visible'] {
|
||||
@apply !bg-white;
|
||||
}
|
||||
|
||||
.dark [data-rmiz-modal-overlay='visible'],
|
||||
[data-theme*='dark'] [data-rmiz-modal-overlay='visible'] {
|
||||
@apply !bg-[#171717];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user