Diagrams

Diagram blocks are wdoc's way of drawing diagrams and charts on pages. A diagram is made of shapes that break down into primitive shapes and render as SVG, which lets the same source target different backends.

The diagram block

Diagrams have the following properties that can be set.

PropertyTypeRequiredDescription
widthi64yesDiagram canvas width in pixels.
heighti64yesDiagram canvas height in pixels.
ididentifiernoOptional explicit HTML id.
classlist<utf8>noOptional style classes.
layoutsymbolnoLayout mode: :free (default, manual x/y) / :grid / :layered / :force / :radial.
directionsymbolnoFlow direction for :layered: :toptobottom (default) / :lefttoright.
layer_gapf64noSpacing between ranks (layers) in :layered layout.
node_gapf64noSpacing between nodes within a rank in :layered layout.
cell_widthf64noGrid cell width for :grid layout.
cell_heightf64noGrid cell height for :grid layout.
columnsi64noNumber of columns for :grid layout.
gapf64noGap between cells in :grid layout.
iterationsi64no:force relaxation steps (default 300).
repulsionf64no:force node repulsion strength (default 9000).
link_distancef64no:force ideal edge-to-edge length (default 60).
gravityf64no:force centering pull (default 0.05).
seedi64no:force random seed for reproducible layouts (default 1).
hubidentifierno:radial hub shape id (defaults to the highest-degree shape).
radiusf64no:radial radius of the first ring (default: auto-fit to shape sizes).
ring_gapf64no:radial added radius per successive ring (default 120).
start_anglef64no:radial angle (radians) of the first shape on each ring (default -PI/2, i.e. top).
routingsymbolnoEdge routing: :elbow (default) / :straight.
edge_separationf64noNudge step that separates parallel edges (default 4).
pan_zoomboolnoWhen true, wrap in an interactive viewport with wheel-zoom, drag-pan, and +// controls.
zoom_minf64noMinimum zoom scale; 1.0 = fitted view (default 1.0).
zoom_maxf64noMaximum zoom scale (default 4.0).
pan_marginf64noExtra overscroll past the content bounds, in px (default 0).
descutf8noAccessible description: becomes the SVG's <title> and aria-label, so screen readers can announce the diagram.
edgeslist<Edge>yesEdges connecting shapes (a -> b).

Child blocks

SlotAcceptsMultipleDescription
childrenSvgBlockyesThe shapes drawn in the diagram.

For accessibility, give a diagram a desc — it becomes the SVG's <title> and aria-label, so screen readers announce the diagram instead of skipping it.

Pan & zoom

Set pan_zoom = true to wrap the diagram in an interactive viewport. Wheel zooms toward the cursor, drag pans, the corner buttons zoom about centre / reset. Zoom is clamped to [zoommin, zoommax]; pan allows half-a-viewport of overscroll past each content edge plus the author's pan_margin. Try it on the diagram below:

diagram {
  width = 320  height = 160  pan_zoom = true
  zoom_min = 0.5  zoom_max = 4.0
  rect { id = a  x = 20.0   y = 30.0  width = 80.0  height = 50.0  fill = "#88c0d0" }
  rect { id = b  x = 210.0  y = 90.0  width = 80.0  height = 50.0  fill = "#a3be8c" }
  a -> b
}

Linking shapes to pages

Give any shape a link to turn it into a hyperlink: clicking the box/pill navigates to that page — handy when each shape stands for a node that has its own page. The target resolves exactly like a prose link: a bare page name → page.html, a cross-site site:page, and an unknown page fails the build the same way a bad markdown link does. Try clicking the shape below:

Primitive shapes
diagram { width = 320  height = 100
  process "Primitive shapes" { link = "wdoc_primitives" }
}

Because SVG/HTML anchors can't nest, don't put link on a container whose children are also linked — link the container's title label instead. On a pan_zoom diagram a plain click still navigates, while a drag-to-pan that happens to end on a linked shape does not.

Styling shapes with classes

Every shape takes a class list, just like text. A class emits SVG paint properties — fill, stroke, stroke_width, stroke_linecap, stroke_linejoin, opacity — with dark { } / light { } overrides, so you style shapes the same way you style prose. Prefer a class over an inline fill = … so a shape follows the site theme and the reader's light/dark mode.

// Declared at the top level (apply site-wide). Hyphenated names may be
// written bare (`class dgm-box`) or quoted.
class "dgm-box" {
  fill         = "#5e81ac"
  stroke       = "#2e3440"
  stroke_width = "2"
  dark  { fill = "#88c0d0"  stroke = "#eceff4" }
  light { fill = "#5e81ac"  stroke = "#2e3440" }
}
class "dgm-ghost" {
  fill    = "#a3be8c"
  opacity = "0.5"
}

diagram { width = 320  height = 120
  rect { x = 20.0   y = 25.0  width = 110.0  height = 70.0  class = ["dgm-box"] }
  rect { x = 160.0  y = 25.0  width = 110.0  height = 70.0  class = ["dgm-ghost"] }
}

The SVG paint fields a class understands on a shape:

FieldEffect
fillInterior colour.
strokeOutline colour.
stroke_widthOutline thickness.
stroke_linecap / stroke_linejoinLine end / corner style.
opacityOverall transparency (01).
dark { } / light { }Per-colour-scheme overrides.

Built-in shape classes work the same way — redeclare a quoted name to recolour it everywhere. For example, the chart palette (wdoc-series-1..wdoc-series-8) or the timeline parts:

class "wdoc-series-1" {
  fill   = "#bf616a"
  stroke = "#bf616a"
  dark  { fill = "#d08770" }
}