Libraries
Visualize
activeCharts for Elixir and Phoenix LiveView, described as data and rendered on the server as SVG or canvas.
What it is
Visualize is a data-visualization library for Elixir and Phoenix LiveView. You describe a chart as plain data, apply your rows on the server, and get SVG or canvas output that drops straight into a HEEx template.
The problem it solves
Putting a chart in a LiveView app usually means leaving Elixir: a JavaScript charting library, a build step to bundle it, and glue code to keep its state in step with the server. The chart ends up as code in the browser, which you cannot store, check or reuse from Elixir.
Visualize keeps the whole chart on the server. There is no JavaScript charting library and no JS build step; charts render in Elixir and LiveView sends only what changed.
Example
A design is composed from fragments, applied to rows, and rendered:
import Visualize.Chart.Build
{:ok, design} =
Visualize.Chart.compose([
chart(meta: %{name: "Daily total"}),
source(:days, [:date, :value]),
cartesian(margin: %{top: 20, right: 20, bottom: 30, left: 40}),
time_scale(:x),
linear_scale(:y, domain: [0, :auto], nice: true),
axis(:x, :bottom),
axis(:y, :left, grid: true),
line(:days, %{x: :date, y: :value}, style: %{curve: :step_after})
])
rows = [%{date: ~D[2024-01-01], value: 10}, %{date: ~D[2024-01-02], value: 25}]
{:ok, applied} = Visualize.Chart.apply(design, sources: %{days: rows}, size: {500, 300})
Visualize.Chart.render(applied, root: true) # an <svg> document
Visualize.Chart.render(applied, backend: :canvas) # Canvas 2D commands
The design records no size; the host supplies one when the chart is applied.
Design notes
- A chart is data. A design is a plain map that can be stored, validated, composed, edited and round-tripped through JSON. Designs are versioned and are checked when loaded from a source you don't control.
- One design, five backends. The same design draws as SVG, Canvas, a binary canvas stream, a hybrid of SVG furniture under canvas marks, or an incremental strip.
- Live and dense data. A compiled chart ticks with new rows and streams them over the LiveView socket, with a data rate independent of the frame rate, so tens of thousands of points can scroll smoothly.
- The d3 model in Elixir. Eleven scale types, shapes with ten curves, axes with number and time formatting, hierarchy and network layouts, geographic projections, Voronoi and contours.
- Themes and a style grammar. One style serves both SVG (as CSS variables) and canvas. Data never names a color; themes choose every color, including meaning-bearing ramps that hold under dark and color-blind-safe themes.
- No required runtime dependencies. Phoenix, Nx and
tableare optional. - Specified and gated. Every public function has a written contract, and CI fails when the specification and the code drift apart.
Where it is going
Visualize is growing from a chart library into a dashboard library that applications share. Beyond designs, it adds feeds (data sources that describe their fields by meaning and deliver rows, implemented through a Visualize.Feed behaviour with a conformance check you can run in your own test suite), boards (designs laid out on a grid with a shared time window, linked selection and drill-down, each cell in its own process so one slow chart never stalls the rest), and a chart builder LiveComponent for editing designs, themes and boards in the browser. These layers are new and expected to settle over the next few releases.
The repository includes a Phoenix example app with a gallery of every chart type.
Status
Visualize is published on Hex and is pre-1.0: its API can still change between releases, and the chart builder is a work in progress. Feedback and bug reports are welcome on GitHub. MIT licensed.