meta/notes / diagrams

Theme-aware diagrams

Killing every ┌──► on the site and replacing them with SVGs that follow the theme picker around the page.

What we had

Project pages and the stack writeup were full of ASCII art:

RTL.v ──► simulate ──► synthesize ──► floorplan ──► place ──► CTS ──► route ──► signoff ──► GDS ──► fab
   |          |             |             |          |        |        |          |          |
 you      iverilog        yosys       openroad   openroad  openroad  openroad   magic +     skywater

This works in plain text and in Verilog comments where we actually want it (humans reading source code), but on a styled site it sticks out as unstyled monospace among the rest of the typography. It also doesn’t re-flow at narrow widths — just wraps mid-arrow.

What we wanted

The pick: beautiful-mermaid

beautiful-mermaid from Craft Labs hits all four points. It’s a re-implementation of Mermaid’s renderer (using ELK.js for layout) that:

Net effect: a single rendered SVG that re-skins instantly when the theme picker changes the underlying daisyUI variables. No re-render, no JavaScript at runtime, no flash.

The component

The whole thing is one file, site/src/components/Diagram.astro. The relevant part of the frontmatter:

const svg = renderMermaidSVG(code, {
  bg:      'var(--diagram-bg, transparent)',
  fg:      'var(--diagram-fg)',
  accent:  'var(--diagram-accent)',
  line:    'var(--diagram-line)',
  muted:   'var(--diagram-muted)',
  border:  'var(--diagram-border)',
  surface: 'var(--diagram-surface)',
  transparent: true,
});

The matching CSS keys those custom properties to the daisyUI theme:

.diagram {
  --diagram-fg:      var(--color-base-content);
  --diagram-accent:  var(--color-primary);
  --diagram-line:    color-mix(in oklab, var(--color-base-content) 55%, transparent);
  --diagram-muted:   color-mix(in oklab, var(--color-base-content) 45%, transparent);
  --diagram-border:  color-mix(in oklab, var(--color-base-content) 30%, transparent);
  --diagram-surface: color-mix(in oklab, var(--color-base-content) 6%, transparent);
}

When daisyUI rotates --color-base-content and --color-primary on the <html data-theme=...> element, every <svg> on the page inherits the new values via the CSS cascade.

Authoring

In MDX, a diagram is a child template literal:

<Diagram caption="The harden flow" code={`
  graph LR
    RTL --> SIM["simulate<br/>iverilog"]
    SIM --> SYN["synthesize<br/>yosys"]
    SYN --> FP["floorplan<br/>OpenROAD"]
    FP --> GDS
`} />

Everything else — layout, styling, theme reactivity — falls out of the component. There’s no build-step file watcher, no exported .svg to keep in public/, no separate diagram source files. The diagram source lives next to the prose that motivates it.

A live one

Same <Diagram> component as elsewhere on the site. Try the theme picker in the header — the colors below shift in lockstep with the prose around them.

RTL.v simulateiverilog synthesizeyosys floorplanOpenROAD placeOpenROAD CTS route signoffmagic + klayout + netgen GDS fab
The same flow as the ASCII version above, rendered through the new component. Try a theme switch.

Caveats and trade-offs

A few corners worth knowing about:

Future hooks

If we ever want runtime Mermaid editing (e.g. an interactive “explore the FSM” widget) we’d add a thin client-side wrapper that calls the same renderMermaidSVG from a browser bundle, keyed on a textarea’s contents. The library is built for this — synchronous, zero DOM dependencies, works in the browser too — but we don’t need it yet on a static site.