PetalComponents.Chart (petal_components v4.8.0)

Copy Markdown View Source

Declarative charts powered by Apache ECharts, themed by your design tokens.

The chart is described by a plain Elixir map — the ECharts option object — so the whole spec lives server-side and travels the LiveView wire as data. Updating the assign that feeds option patches the chart in place with an animated transition; no JavaScript is written per chart.

<.chart
  id="revenue"
  option={%{
    xAxis: %{type: "category", data: ~w(Jan Feb Mar Apr)},
    yAxis: %{type: "value"},
    series: [%{type: "line", smooth: true, data: [820, 932, 901, 1290]}]
  }}
/>

Bring your own ECharts

Like Alpine, the library does not bundle the engine. Add ECharts to your app (either is fine):

<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>

or npm i echarts and import * as echarts from "echarts"; window.echarts = echarts; in your app.js. The PetalChart hook (in the bundled JS) picks it up from window.echarts and warns if it is missing.

Theming

Colors are resolved from your CSS tokens at mount, so charts follow the same dial as every other component — light and dark:

  • Series palette--pc-chart-1--pc-chart-8 if you define them, otherwise a default palette derived from your semantic ramps (primary, info, success, warning, danger, secondary).
  • Axes, labels, gridlines, tooltips — derived from the gray ramp, using the same ghost-material alphas as the rest of the library in dark mode.

Anything you set explicitly in option wins over the derived theme.

A few conveniences fill the gap between a server-side spec and things only the client knows (resolved colors, number formatting functions):

  • areaStyle: %{color: "petal:fade"} on a line series renders the soft vertical gradient fade (the series' own color at 35% fading to transparent) without you having to know the resolved palette.

  • When falling back to the semantic ramps, ramps whose hue collides with an earlier pick (success green under an emerald primary, say) are pushed to the back of the palette so adjacent series stay distinct.

  • Named formatters - ECharts formats numbers via JavaScript callback functions, which can't travel the wire. Anywhere ECharts accepts a formatter (axisLabel, tooltip.valueFormatter, series labels), pass one of these strings instead and the hook substitutes an Intl.NumberFormat-backed function:

    • "petal:number" - compact: 1234 → "1.2K"
    • "petal:percent" - value as given plus %: 8.3 → "8.3%"
    • "petal:currency:USD" - full: 12480 → "$12,480" (any ISO code)
    • "petal:currency-compact:USD" - axes: 12480 → "$12K"

    For example: yAxis: %{axisLabel: %{formatter: "petal:currency-compact:USD"}}, tooltip: %{trigger: "axis", valueFormatter: "petal:currency:USD"}.

The theme re-derives automatically when dark mode flips or theme attributes change anywhere above the chart (class, data-theme, data-primary, data-gray, ...). If your app rethemes some other way, dispatch window.dispatchEvent(new Event("petal:retheme")) after changing tokens.

Live updates

Change the assign and the chart animates — this is the primary API:

def handle_info({:tick, points}, socket) do
  {:noreply, assign(socket, option: put_in(socket.assigns.option, [:series, Access.at(0), :data], points))}
end

For high-frequency streams where re-serializing the full option is wasteful, push a partial option instead; it is merged via setOption:

push_event(socket, "chart:update:revenue", %{option: %{series: [%{data: points}]}})

Summary

Functions

Renders an ECharts chart bound to the PetalChart hook.

Functions

chart(assigns)

Renders an ECharts chart bound to the PetalChart hook.

Attributes

  • id (:string) (required)
  • option (:map) (required) - the ECharts option object as an Elixir map (atom or string keys).
  • height (:string) - any CSS height; the chart fills its container's width. Defaults to "20rem".
  • renderer (:string) - svg renders crisp at any zoom and is print-friendly; canvas suits large data. Defaults to "canvas". Must be one of "canvas", or "svg".
  • group (:string) - charts sharing a group name get connected tooltips/zoom (echarts.connect). Defaults to nil.
  • loading (:boolean) - shows a theme-colored loading spinner over the chart while your data is on its way. Defaults to false.
  • class (:any) - Defaults to nil.
  • Global attributes are accepted.