Powered by AppSignal & Oban Pro

ChartsEx Examples

examples/charts_ex.livemd

ChartsEx Examples

Mix.install([
  {:charts_ex, path: "."},
  {:kino, "~> 0.14"}
])

Bar Chart

A dual-series bar chart with the Grafana theme:

alias ChartsEx.BarChart

svg =
  BarChart.new()
  |> BarChart.title("Quarterly Sales by Region")
  |> BarChart.sub_title("FY 2025 - All figures in $k")
  |> BarChart.theme(:grafana)
  |> BarChart.width(700)
  |> BarChart.height(420)
  |> BarChart.x_axis(["Q1", "Q2", "Q3", "Q4"])
  |> BarChart.add_series("North America", [312.0, 348.0, 295.0, 410.0])
  |> BarChart.add_series("Europe", [228.0, 265.0, 241.0, 302.0])
  |> BarChart.series_colors(["#5470C6", "#91CC75"])
  |> BarChart.legend_align(:right)
  |> BarChart.radius(4.0)
  |> ChartsEx.render!()

Kino.HTML.new(svg)

Line Chart

Smooth curves with area fill and mark lines:

alias ChartsEx.LineChart

svg =
  LineChart.new()
  |> LineChart.title("Server Response Times")
  |> LineChart.sub_title("p50 and p99 latency in ms")
  |> LineChart.theme(:grafana)
  |> LineChart.width(700)
  |> LineChart.height(400)
  |> LineChart.smooth(true)
  |> LineChart.fill(true)
  |> LineChart.x_axis(["00:00", "04:00", "08:00", "12:00", "16:00", "20:00", "23:59"])
  |> LineChart.add_series("p50", [12.0, 8.0, 35.0, 62.0, 48.0, 24.0, 14.0])
  |> LineChart.add_series("p99", [45.0, 28.0, 120.0, 210.0, 165.0, 78.0, 52.0],
    mark_lines: [%{category: "average"}],
    mark_points: [%{category: "max"}]
  )
  |> LineChart.series_colors(["#73C0DE", "#EE6666"])
  |> ChartsEx.render!()

Kino.HTML.new(svg)

Pie Chart (Donut)

Browser market share as a donut chart:

alias ChartsEx.PieChart

svg =
  PieChart.new()
  |> PieChart.title("Browser Market Share")
  |> PieChart.sub_title("Global - March 2025")
  |> PieChart.theme(:westeros)
  |> PieChart.width(500)
  |> PieChart.height(400)
  |> PieChart.inner_radius(80.0)
  |> PieChart.radius(150.0)
  |> PieChart.border_radius(4.0)
  |> PieChart.add_series("Chrome", [64.7])
  |> PieChart.add_series("Safari", [18.6])
  |> PieChart.add_series("Firefox", [3.2])
  |> PieChart.add_series("Edge", [5.3])
  |> PieChart.add_series("Other", [8.2])
  |> PieChart.series_colors(["#5470C6", "#91CC75", "#FAC858", "#EE6666", "#73C0DE"])
  |> ChartsEx.render!()

Kino.HTML.new(svg)

Radar Chart

Framework comparison across multiple dimensions:

alias ChartsEx.RadarChart

svg =
  RadarChart.new()
  |> RadarChart.title("Framework Comparison")
  |> RadarChart.sub_title("Phoenix vs. Rails vs. Next.js")
  |> RadarChart.theme(:vintage)
  |> RadarChart.width(560)
  |> RadarChart.height(460)
  |> RadarChart.indicators([
    %{name: "Performance", max: 100.0},
    %{name: "Scalability", max: 100.0},
    %{name: "Ecosystem", max: 100.0},
    %{name: "Learning Curve", max: 100.0},
    %{name: "Realtime", max: 100.0},
    %{name: "Deployment", max: 100.0}
  ])
  |> RadarChart.add_series("Phoenix", [92.0, 95.0, 58.0, 55.0, 98.0, 72.0])
  |> RadarChart.add_series("Rails", [65.0, 70.0, 90.0, 75.0, 50.0, 80.0])
  |> RadarChart.add_series("Next.js", [78.0, 72.0, 95.0, 68.0, 65.0, 88.0])
  |> RadarChart.series_colors(["#6C5CE7", "#E17055", "#00B894"])
  |> ChartsEx.render!()

Kino.HTML.new(svg)

Horizontal Bar Chart

alias ChartsEx.HorizontalBarChart

svg =
  HorizontalBarChart.new()
  |> HorizontalBarChart.title("Top Programming Languages by Job Postings")
  |> HorizontalBarChart.theme(:ant)
  |> HorizontalBarChart.width(650)
  |> HorizontalBarChart.height(400)
  |> HorizontalBarChart.x_axis(["Elixir", "Go", "Rust", "TypeScript", "Python", "Java"])
  |> HorizontalBarChart.add_series("Job Postings (thousands)", [
    8.4, 22.1, 12.7, 58.3, 92.5, 74.0
  ], label_show: true)
  |> HorizontalBarChart.series_colors(["#5470C6"])
  |> ChartsEx.render!()

Kino.HTML.new(svg)

Scatter Chart

alias ChartsEx.ScatterChart

svg =
  ScatterChart.new()
  |> ScatterChart.title("House Price vs. Square Footage")
  |> ScatterChart.sub_title("Austin, TX - 2025 listings")
  |> ScatterChart.theme(:walden)
  |> ScatterChart.width(650)
  |> ScatterChart.height(420)
  |> ScatterChart.add_series("3-Bedroom", [
    [1200.0, 285.0], [1450.0, 320.0], [1680.0, 375.0],
    [1890.0, 410.0], [2100.0, 465.0], [2350.0, 520.0]
  ])
  |> ScatterChart.add_series("4-Bedroom", [
    [1800.0, 420.0], [2050.0, 485.0], [2300.0, 540.0],
    [2600.0, 610.0], [2850.0, 675.0], [3100.0, 740.0]
  ])
  |> ScatterChart.symbol_sizes([6.0, 8.0])
  |> ScatterChart.series_colors(["#5470C6", "#EE6666"])
  |> ChartsEx.render!()

Kino.HTML.new(svg)

Candlestick Chart

alias ChartsEx.CandlestickChart

svg =
  CandlestickChart.new()
  |> CandlestickChart.title("AAPL Stock Price")
  |> CandlestickChart.sub_title("Weekly - Jan to Mar 2025")
  |> CandlestickChart.theme(:dark)
  |> CandlestickChart.width(750)
  |> CandlestickChart.height(420)
  |> CandlestickChart.up_color("#26A69A")
  |> CandlestickChart.up_border_color("#26A69A")
  |> CandlestickChart.down_color("#EF5350")
  |> CandlestickChart.down_border_color("#EF5350")
  |> CandlestickChart.x_axis([
    "Jan 6", "Jan 13", "Jan 20", "Jan 27",
    "Feb 3", "Feb 10", "Feb 17", "Feb 24",
    "Mar 3", "Mar 10", "Mar 17", "Mar 24"
  ])
  |> CandlestickChart.add_series("AAPL", [
    [243.0, 248.5, 240.1, 250.3],
    [248.5, 252.0, 246.2, 254.7],
    [252.0, 245.8, 243.5, 253.0],
    [245.8, 249.2, 244.0, 251.5],
    [249.2, 256.3, 248.0, 258.1],
    [256.3, 261.0, 254.5, 263.8],
    [261.0, 258.4, 255.2, 262.5],
    [258.4, 264.7, 257.0, 266.3],
    [264.7, 260.1, 258.3, 266.0],
    [260.1, 268.5, 259.0, 270.2],
    [268.5, 272.3, 266.8, 275.0],
    [272.3, 270.8, 268.5, 274.1]
  ])
  |> ChartsEx.render!()

Kino.HTML.new(svg)

Heatmap Chart

alias ChartsEx.HeatmapChart

svg =
  HeatmapChart.new()
  |> HeatmapChart.title("Deploy Frequency by Day and Hour")
  |> HeatmapChart.theme(:grafana)
  |> HeatmapChart.width(700)
  |> HeatmapChart.height(340)
  |> HeatmapChart.x_axis(["Mon", "Tue", "Wed", "Thu", "Fri"])
  |> HeatmapChart.y_axis(["9 AM", "11 AM", "1 PM", "3 PM", "5 PM"])
  |> HeatmapChart.series(%{
    data: [
      [0, 0, 3],  [0, 1, 5],  [0, 2, 8],  [0, 3, 12], [0, 4, 4],
      [1, 0, 7],  [1, 1, 11], [1, 2, 15], [1, 3, 9],  [1, 4, 2],
      [2, 0, 10], [2, 1, 18], [2, 2, 22], [2, 3, 14], [2, 4, 6],
      [3, 0, 5],  [3, 1, 8],  [3, 2, 19], [3, 3, 16], [3, 4, 7],
      [4, 0, 2],  [4, 1, 6],  [4, 2, 13], [4, 3, 10], [4, 4, 1]
    ],
    min: 0,
    max: 25,
    min_color: "#E0F3F8",
    max_color: "#0B3D91"
  })
  |> ChartsEx.render!()

Kino.HTML.new(svg)

Table Chart

alias ChartsEx.TableChart

svg =
  TableChart.new()
  |> TableChart.title("Q1 2025 - SaaS Metrics")
  |> TableChart.theme(:light)
  |> TableChart.width(680)
  |> TableChart.height(300)
  |> TableChart.data([
    ["Metric", "January", "February", "March", "Trend"],
    ["MRR", "$142,300", "$148,900", "$156,200", "+9.8%"],
    ["Churn Rate", "2.1%", "1.8%", "1.6%", "-0.5pp"],
    ["New Customers", "87", "104", "119", "+36.8%"],
    ["NPS Score", "62", "65", "71", "+9pts"],
    ["Avg. Deal Size", "$4,280", "$4,510", "$4,750", "+11.0%"]
  ])
  |> TableChart.spans([2.0, 1.0, 1.0, 1.0, 1.0])
  |> TableChart.text_aligns([:left, :right, :right, :right, :right])
  |> TableChart.header_background_color("#4A5568")
  |> TableChart.header_font_color("#FFFFFF")
  |> TableChart.body_background_colors(["#F7FAFC", "#EDF2F7"])
  |> TableChart.border_color("#CBD5E0")
  |> ChartsEx.render!()

Kino.HTML.new(svg)

Theme Gallery

Render the same chart across all 9 themes:

alias ChartsEx.BarChart

charts =
  for theme <- ChartsEx.Theme.list() do
    svg =
      BarChart.new()
      |> BarChart.title("#{theme} theme")
      |> BarChart.theme(theme)
      |> BarChart.width(400)
      |> BarChart.height(280)
      |> BarChart.x_axis(["Jan", "Feb", "Mar", "Apr", "May"])
      |> BarChart.add_series("Revenue", [42.0, 48.0, 53.0, 51.0, 60.0])
      |> BarChart.add_series("Costs", [28.0, 32.0, 35.0, 41.0, 38.0])
      |> ChartsEx.render!()

    Kino.HTML.new(svg)
  end

Kino.Layout.grid(charts, columns: 3)