Usage#

Place a diagram with <Mermaid>, configure the palette once, and let it follow the page's theme.

The component#

TSX
import { Mermaid } from '@sigx/mermaid';

<Mermaid code="graph TD; A-->B;" title="Flow" />
<Mermaid code={source} eager />
PropTypeDescription
codestringRequired. The diagram definition.
titlestringRendered as a <figcaption> and used as the SVG's accessible name.
optionsMermaidOptionsPer-instance overrides, merged over the global config.
eagerbooleanRender on mount instead of on scroll-into-view. Default false.

Anything else lands on the <figure>id, class, style, data-*, aria-*, DOM event handlers. class is composed with the component's own rather than replacing it:

TSX
<Mermaid code={source} id="architecture" class="my-diagram" />
// → <figure class="sigx-mermaid my-diagram" id="architecture" …>

title is the exception: it is this component's caption, so it is not forwarded as the HTML tooltip attribute.

The source is emitted as a <pre> and only hidden once the SVG lands. So a diagram that has not rendered — no JavaScript yet, or a syntax error — still shows its definition instead of a blank frame.

Configuration#

Set global options once, wherever your app starts up:

TypeScript
import { configureMermaid } from '@sigx/mermaid';

configureMermaid({
    themes: { light: 'neutral', dark: 'dark' },
    config: { flowchart: { curve: 'basis' } },
});

Calls merge, so several modules can each contribute a slice, and any component can override with options.

OptionDefaultDescription
themes{ light: 'default', dark: 'dark' }Appearance per colour scheme.
securityLevel'strict'Passed to mermaid. Raising it lets diagrams emit raw HTML and click handlers.
config{}Merged into mermaid.initialize(). themeVariables merges rather than replaces.
resolveColorSchemeOverride colour-scheme detection entirely.

Matching your palette#

Each scheme takes a mermaid theme name or { theme, variables }:

TypeScript
configureMermaid({
    themes: {
        light: { theme: 'base', variables: { primaryColor: '#f6f8fa', lineColor: '#d1d9e0' } },
        dark: { theme: 'base', variables: { primaryColor: '#161b22', lineColor: '#3d444d' } },
    },
});

Pair variables with theme: 'base'base is the theme mermaid intends to be recoloured; the others largely ignore overrides.

variables may be a function, evaluated at render time rather than at config time. That is how diagrams track a daisyUI or Tailwind theme swap without restating the palette:

TypeScript
const cssVar = (n: string) => getComputedStyle(document.documentElement).getPropertyValue(n).trim();

const fromTokens = () => ({
    background: cssVar('--b1'),
    primaryColor: cssVar('--b2'),
    primaryTextColor: cssVar('--bc'),
    lineColor: cssVar('--bc'),
});

configureMermaid({
    themes: { light: { theme: 'base', variables: fromTokens }, dark: { theme: 'base', variables: fromTokens } },
});

Precedence, lowest first: package defaults → global config → per-call options.config → the active scheme's variables. themeVariables merges at each step, so overriding one colour keeps the rest.

The one variable the package sets#

VariableDefaultWhy
edgeLabelBackgroundthe page backgroundmermaid hardcodes a light grey in every built-in theme, including the dark ones, so an edge label lands as a highlighter smear across a dark diagram.

The page background rather than transparent, because the chip's job is to occlude the line running under it. Set it yourself to override — 'transparent' included. When no background is painted the canvas is white, which is what mermaid's default already assumes, so nothing is applied.

Theme detection#

In order, first match wins:

  1. an explicit resolveColorScheme
  2. data-theme of exactly light / dark on <html>
  3. the computed color-scheme — how named daisyUI themes like night or cupcake resolve
  4. a .dark class on <html> (the Tailwind convention)
  5. the page's actual background colour

Note what is not on that list: prefers-color-scheme. A page that has not opted into dark mode renders light no matter what the OS prefers, so keying off the OS puts a dark diagram on a white page.

Reading the background answers the question actually being asked — is this diagram about to sit on something dark? — and it works whether the site themes itself with data-theme, a class, or a bare @media (prefers-color-scheme: dark) block that declares no color-scheme. A page with no background at all is canvas white, so: light.

If your page is dark in a way none of these can see, say so directly:

TypeScript
configureMermaid({ resolveColorScheme: () => (myStore.dark ? 'dark' : 'light') });

Re-rendering#

When the resolved appearance changes, already-rendered diagrams re-render; ones that have not drawn yet pick up the new theme when they do.

"Changes" means the colour scheme, the theme name, or the resolved variables — all three, because with per-scheme variables both schemes usually name base, and a daisyUI swap between two light themes changes neither the scheme nor the name while changing every colour.

The watcher fires on data-theme / class / style mutations on <html> and on prefers-color-scheme. A theme delivered purely by swapping a stylesheet is not observable — call renderDiagram again, or toggle an attribute.

Styling#

@sigx/mermaid/styles is cosmetic. Everything functional is done in JS with the hidden attribute, so a site that skips the stylesheet still behaves correctly.

Override the custom properties on .sigx-mermaid: --sigx-mermaid-gap, --sigx-mermaid-radius, --sigx-mermaid-padding, --sigx-mermaid-bg, --sigx-mermaid-border, --sigx-mermaid-muted, --sigx-mermaid-error, --sigx-mermaid-min-height.

Next steps#