Skip to content
commit-766c8d6756a1

Chart architecture

Static/vector and interactive charts

Choose the delivery model from the job the chart must do. Both families share theme tokens, accessible framing, and chart controls, but their runtime, output, and failure behavior differ substantially.

Choose a mode

Static/vector

Prefer it for server-rendered pages, reports, print, email image capture, scalable artifacts, and resilient first paint. The chart itself is inline SVG.

Interactive

Prefer it when exploration, hover detail, chart-specific zoom, live categorical snapshots, or a continuously synchronized theme justify a browser runtime and canvas.

Capability comparison

Interactive is not an upgrade tier, and static is not a reduced preview. They solve different delivery and exploration problems.

CapabilityStatic/vectorInteractive
Output and deliveryInline SVG is rendered with the HTML response. The chart image needs no browser renderer.A browser runtime initializes a canvas after the HTML response arrives.
JavaScriptNone for the chart image. Expand, fullscreen, and export still use the shared control runtime when enabled.Required for drawing, interaction, theme synchronization, export, and optional live updates.
ExportSVG and browser-rasterized PNG are available by default. Transparent output is supported.PNG snapshots are available by default. SVG and transparent output are not supported.
Print and documentsBest when scalable marks, selectable text, and stable server output matter.Prints as rendered pixels. Export a PNG or provide a static sibling when the artifact must be stable.
ExplorationNo tooltips, zoom, or live state in the chart image.Typed options can enable tooltips. Zoom exists only on chart types that expose it, currently candlestick.
Live data and themesTheme tokens update SVG presentation through CSS without redrawing the chart.The chart instance follows theme changes. Categorical Bar and Line can consume full-snapshot SSE updates.
Exact valuesSVG geometry is still not a substitute for exact data. Keep the component's disclosure or an adjacent table when precision matters.Canvas pixels are not an accessible data model. Keep caption, summaries, and an adjacent equivalent data view.
Failure modeInvalid configuration fails during server rendering. If control JavaScript is blocked, the SVG remains visible but actions do not work.Invalid configuration fails during server rendering. If runtime or initialization is blocked, the canvas cannot become a usable chart.

Wrapper lifecycle is independent of renderer choice. Every chart accepts the same enabled, disabled, hidden, or omitted wrapper state; review chart controls and wrapper lifecycle before choosing client-side transitions.

Shared wrapper boundary

Renderer stays the same

Expand and fullscreen change layout, not chart delivery. A static chart remains SVG; an interactive chart remains its live browser-rendered canvas.

Omitted removes only the wrapper

Omitted removes shared actions and lifecycle runtime. It does not turn an interactive chart into server-rendered output or remove that chart's browser dependency.

Features remain chart-specific

Interactive does not promise zoom, live data, selection, or animation for every chart type. Use only options documented by that component. Static output does not gain those chart interactions from the wrapper.

Equivalent data remains separate

Neither SVG geometry nor canvas pixels replace exact values, reading order, or relationships. Keep the component's disclosure or a caller-owned table, summary, or download.

Render the same data two ways

Static/vector

templ
@line.Line(line.Config{
  Label:   "Weekly revenue",
  Caption: "Revenue for the last five business days.",
  Labels:  []string{"Mon", "Tue", "Wed", "Thu", "Fri"},
  Series: []line.Series{{
    Name: "Revenue",
    Values: []float64{12, 18, 14, 24, 21},
  }},
})

Interactive

templ
@interactiveline.Line(interactiveline.Config{
  Label:   "Weekly revenue",
  Caption: "Hover for values; use the adjacent table for exact data.",
  XAxis:   []string{"Mon", "Tue", "Wed", "Thu", "Fri"},
  Series: []interactiveline.Series{{
    Name: "Revenue",
    Data: []interactiveline.Data{
      {Value: 12}, {Value: 18}, {Value: 14}, {Value: 24}, {Value: 21},
    },
  }},
  Options: interactive.ChartOptions{
    Tooltip: &interactive.TooltipOptions{
      Show: interactive.Bool(true),
      Trigger: "axis",
    },
  },
})

Assets and CSP

Interactive charts require the versioned local assets handler and dependencies.Dependencies(); hosted delivery is an explicit opt-in. Dependency tags inherit a templ nonce. The current per-chart initializer, theme, and live-update scripts do not yet accept a nonce, so a strict nonce-only script policy is not fully supported for interactive charts. Static chart images avoid those initializer scripts, although enabled controls still load their same-origin external runtime.

Go API

v0.0.1

These guides explain behavior and composition. pkg.go.dev is the canonical reference for exported types, functions, methods, and Go documentation.

Related guideChart controls