diff --git a/apps/design-system/__registry__/index.tsx b/apps/design-system/__registry__/index.tsx index e2bc55b003c..06f5d1ad19a 100644 --- a/apps/design-system/__registry__/index.tsx +++ b/apps/design-system/__registry__/index.tsx @@ -2601,13 +2601,46 @@ export const Index: Record = { 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: [] diff --git a/apps/design-system/content/docs/components/mermaid.mdx b/apps/design-system/content/docs/components/mermaid.mdx index 22e49fe3ef9..3133c9504f8 100644 --- a/apps/design-system/content/docs/components/mermaid.mdx +++ b/apps/design-system/content/docs/components/mermaid.mdx @@ -4,85 +4,123 @@ description: Render diagrams from text using Mermaid syntax. component: true --- - - -## Installation - -The Mermaid component is available from the `ui` package: - -```tsx -import { Mermaid } from 'ui' -``` + ## 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 - B[End] +export function MyDiagram() { + return ( + 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 - +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. ---- +### With Subgraphs -### ER Diagram +Group related nodes into labeled subgraphs to show system boundaries. Useful for depicting frontend/backend separation or microservice architecture. - + ---- +### 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. - - ---- - -### Sync Blocking (FDW) - - - ---- + ### 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. + +## 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. + + + +### With Attributes + +Include column definitions with types and constraints (PK, FK) to create more detailed schema documentation. + + + +## 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. + + + +### Async Streaming (FDW) + +Shows how Foreign Data Wrappers can stream data asynchronously using bounded channels, with parallel execution indicated by the `par` block. + + + +### Sync Blocking (FDW) + +Contrasts with async by showing traditional blocking FDW behavior where all rows are fetched and buffered before processing. + + + ## 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. +``` diff --git a/apps/design-system/registry/default/example/mermaid-basic.tsx b/apps/design-system/registry/default/example/mermaid-basic.tsx new file mode 100644 index 00000000000..4fb5c6f2d6f --- /dev/null +++ b/apps/design-system/registry/default/example/mermaid-basic.tsx @@ -0,0 +1,16 @@ +import { Mermaid } from 'ui' + +export default function MermaidBasic() { + return ( + B{Is it working?} + B -->|Yes| C[Great!] + B -->|No| D[Debug] + D --> B + C --> E[End] +`} + /> + ) +} diff --git a/apps/design-system/registry/default/example/mermaid-demo.tsx b/apps/design-system/registry/default/example/mermaid-demo.tsx index dfa6e7bc69a..a282b9d2df9 100644 --- a/apps/design-system/registry/default/example/mermaid-demo.tsx +++ b/apps/design-system/registry/default/example/mermaid-demo.tsx @@ -5,45 +5,25 @@ export default function MermaidDemo() { Auth] - API[PostgREST
REST API] - Realtime[Realtime
WebSockets] - Storage[Storage API
S3-compatible] - Meta[postgres-meta
DB Management] - Functions[Deno
Edge Functions] - GraphQL[pg_graphql
GraphQL] - end - - subgraph Data - Postgres[(PostgreSQL)] - Supavisor[Supavisor
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 `} /> ) diff --git a/apps/design-system/registry/default/example/mermaid-er-simple.tsx b/apps/design-system/registry/default/example/mermaid-er-simple.tsx new file mode 100644 index 00000000000..b49f8e366cf --- /dev/null +++ b/apps/design-system/registry/default/example/mermaid-er-simple.tsx @@ -0,0 +1,14 @@ +import { Mermaid } from 'ui' + +export default function MermaidErSimple() { + return ( + + ) +} diff --git a/apps/design-system/registry/default/example/mermaid-flowchart-subgraph.tsx b/apps/design-system/registry/default/example/mermaid-flowchart-subgraph.tsx new file mode 100644 index 00000000000..5ba8f754fec --- /dev/null +++ b/apps/design-system/registry/default/example/mermaid-flowchart-subgraph.tsx @@ -0,0 +1,21 @@ +import { Mermaid } from 'ui' + +export default function MermaidFlowchartSubgraph() { + return ( + B[API Client] + end + + subgraph Backend + C[Edge Functions] --> D[Database] + C --> E[Storage] + end + + B --> C +`} + /> + ) +} diff --git a/apps/design-system/registry/default/example/mermaid-sequence-api.tsx b/apps/design-system/registry/default/example/mermaid-sequence-api.tsx new file mode 100644 index 00000000000..69050f824dc --- /dev/null +++ b/apps/design-system/registry/default/example/mermaid-sequence-api.tsx @@ -0,0 +1,22 @@ +import { Mermaid } from 'ui' + +export default function MermaidSequenceApi() { + return ( + >API: POST /api/data + API->>Auth: Validate JWT + Auth-->>API: Token valid + API->>DB: INSERT query + DB-->>API: Success + API-->>Client: 201 Created +`} + /> + ) +} diff --git a/apps/design-system/registry/examples.ts b/apps/design-system/registry/examples.ts index 4ac8d96fa35..5a9f1fa4efa 100644 --- a/apps/design-system/registry/examples.ts +++ b/apps/design-system/registry/examples.ts @@ -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'], + }, ] diff --git a/packages/ui/src/components/Mermaid/Mermaid.tsx b/packages/ui/src/components/Mermaid/Mermaid.tsx index 81e29f2770a..c8875b13e4c 100644 --- a/packages/ui/src/components/Mermaid/Mermaid.tsx +++ b/packages/ui/src/components/Mermaid/Mermaid.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 = ( -
+ 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 {content} + // Convert SVG to data URL for react-medium-image-zoom compatibility + const svgDataUrl = `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(svg)))}` + return ( +
+ + Mermaid diagram + +
+ ) } - return content + return ( +
+ ) } diff --git a/packages/ui/src/components/Mermaid/mermaid-zoom.css b/packages/ui/src/components/Mermaid/mermaid-zoom.css new file mode 100644 index 00000000000..2a4907a660c --- /dev/null +++ b/packages/ui/src/components/Mermaid/mermaid-zoom.css @@ -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]; + } +} +