Chart

With careful, minimal styling choices, TRMNL can display a variety of numerical or time centric content as charts and graphs.

Usage

Any CDN-enabled JavaScript library may be used to develop charting interfaces, however the examples below leverage Highcharts and Chartkick.

Line Chart

Line charts effectively display trends over time. This example shows a simple line chart with customized styling to match the TRMNL aesthetic.

25,388 Pageviews
4,771 Visitors
2.23 Mins on Page
Charts Line Chart
<!-- import Highcharts + Chartkick libraries -->
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chartkick.min.js"></script>

<!-- markup with empty, ID'd element for chart injection -->
<div class="view view--full">
  <div class="layout layout--col gap--space-between">
    <div class="grid grid--cols-3">
      <div class="item">
        <div class="meta"></div>
        <div class="content">
          <span class="value value--tnums">25,388</span>
          <span class="label">Pageviews</span>
        </div>
      </div>
      <div class="item">
        <div class="meta"></div>
        <div class="content">
          <span class="value value--tnums">4,771</span>
          <span class="label">Visitors</span>
        </div>
      </div>
      <div class="item">
        <div class="meta"></div>
        <div class="content">
          <span class="value value--tnums">2.23</span>
          <span class="label">Mins on Page</span>
        </div>
      </div>
    </div>

    <div id="chart-123" style="width: 100%"></div>
  </div>

  <div class="title_bar">
    <img class="image" src="https://usetrmnl.com/images/plugins/simple-analytics--render.svg" />
    <span class="title">Simple Analytics</span>
    <span class="instance">usetrmnl.com</span>
  </div>
</div>

<script type="text/javascript">
  var data = [["2024-06-09", 975],["2024-06-10", 840],["2024-06-11", 1004],["2024-06-12", 1308],["2024-06-13", 753],["2024-06-14", 600],["2024-06-15", 710],
              ["2024-06-16", 489],["2024-06-17", 510],["2024-06-18", 590],["2024-06-19", 610],["2024-06-20", 671],["2024-06-21", 512],["2024-06-22", 550],
              ["2024-06-23", 421],["2024-06-24", 315],["2024-06-25", 604],["2024-06-26", 672],["2024-06-27", 601],["2024-06-28", 705],["2024-06-29", 800],
              ["2024-06-30", 912],["2024-07-01", 1503],["2024-07-02", 1273],["2024-07-03", 1250],["2024-07-04", 1198],["2024-07-05", 1005],["2024-07-06", 1300],
              ["2024-07-07", 1103],["2024-07-08", 1004],["2024-07-09", 600]];

  // recommended configs to achieve the TRMNL Framework aesthetic
  var createChart = function() {
    new Chartkick["LineChart"](
    "chart-123",
    data,
    {
      adapter: "highcharts", // chartjs, google, etc available
      prefix: "",
      thousands: ",",
      points: false,
      colors: ["black"],
      curve: true,
      library: {
        chart: {
          height: 260
        },
        plotOptions: {
          series: {
            animation: false,
            lineWidth: 4
          }
        },
        yAxis: {
          labels: {
            style: {
              fontSize: "16px",
              color:"#000000"
            }
          },
          gridLineDashStyle: "shortdot",
          gridLineWidth: 1,
          gridLineColor: "#000000",
          tickAmount: 5
        },
        xAxis: {
          type: "daytime",
          labels: {
            style: {
              fontSize: "16px",
              color: "#000000"
            }
          },
          lineWidth: 0,
          gridLineDashStyle: "dot",
          tickWidth: 1,
          tickLength: 0,
          gridLineWidth: 1,
          gridLineColor: "#000000",
          tickPixelInterval: 120
        }
      }
    });
  };

  // ensure your chart loads before plugin render is generated
  if ("Chartkick" in window) {
    createChart();
  } else {
    window.addEventListener("chartkick:load", createChart, true);
  }
</script>

Gauge Chart

Gauge charts can effectively display single metrics or scores. This example shows multiple gauges in a row with a main summary gauge, perfect for displaying daily and weekly metrics like sleep quality scores.

Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
18% REM Sleep
23% Deep Sleep
12m Time to Sleep
7h 32min Sleep Duration
8 Toss & Turns
0.5% Snoring
Charts Gauge Chart
<!-- import Highcharts libraries -->
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/pattern-fill.js"></script>

<div class="view view--full">
  <div class="layout layout--col gap--none">
    <div class="grid grid--cols-7 mb--5">
      <div class="h--32">
        <div id="day_0" class="h--24"></div>
        <span class="description text--center">Monday</span>
      </div>
      <div class="h--32">
        <div id="day_1" class="h--24"></div>
        <span class="description text--center">Tuesday</span>
      </div>
      <div class="h--32">
        <div id="day_2" class="h--24"></div>
        <span class="description text--center">Wednesday</span>
      </div>
      <div class="h--32">
        <div id="day_3" class="h--24"></div>
        <span class="description text--center">Thursday</span>
      </div>
      <div class="h--32">
        <div id="day_4" class="h--24"></div>
        <span class="description text--center">Friday</span>
      </div>
      <div class="h--32">
        <div id="day_5" class="h--24"></div>
        <span class="description text--center">Saturday</span>
      </div>
      <div class="h--32">
        <div id="day_6" class="h--24"></div>
        <span class="description text--center">Sunday</span>
      </div>
    </div>

    <div class="w-full b-h-gray-5"></div>

    <div class="grid">
      <div class="col--span-1 col--center">
        <div id="day_all" class="w-[340px] mt--5"></div>
      </div>
      <div class="col--span-1 gap--large">
        <div class="flex flex--col gap--medium w--full flex--center">
          <div class="grid grid--cols-2">
            <div class="item">
              <div class="meta"></div>
              <div class="content">
                <span class="value value--tnums">18%</span>
                <span class="label">REM Sleep</span>
              </div>
            </div>
            <div class="item">
              <div class="meta"></div>
              <div class="content">
                <span class="value value--tnums">23%</span>
                <span class="label">Deep Sleep</span>
              </div>
            </div>
          </div>
          <div class="b-h-gray-5 w-full"></div>
          <div class="grid grid--cols-2">
            <div class="item">
              <div class="meta"></div>
              <div class="content">
                <span class="value value--small value--tnums">12m</span>
                <span class="label">Time to Sleep</span>
              </div>
            </div>
            <div class="item">
              <div class="meta"></div>
              <div class="content">
                <span class="value value--small value--tnums">7h 32min</span>
                <span class="label">Sleep Duration</span>
              </div>
            </div>
          </div>
          <div class="b-h-gray-5 w-full"></div>
          <div class="grid grid--cols-2">
            <div class="item">
              <div class="meta"></div>
              <div class="content">
                <span class="value value--small value--tnums">8</span>
                <span class="label">Toss & Turns</span>
              </div>
            </div>
            <div class="item">
              <div class="meta"></div>
              <div class="content">
                <span class="value value--small value--tnums">0.5%</span>
                <span class="label">Snoring</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

<script type="text/javascript">
  var dailyScores = [92, 95, 81, 56, 81, 72, 85];
  var weeklyScore = 82;

  function createGauge(score, day, opts) {
    opts ||= {
      title: null,
      height: "80%",
      labels: {
        distance: 15,
        style: {
          fontSize: "16px"
        }
      },
      series: {
        fontSize: "3em"
      },
      yAxis: {
        title: textRating(score)
      }
    };

    Highcharts.chart(`day_${day}`, {
      chart: {
        type: "gauge",
        height: opts.height
      },

      title: {
        text: opts.title
      },

      pane: {
        startAngle: -150,
        endAngle: 150,
        background: {
          backgroundColor: "transparent",
          borderWidth: 0
        }
      },

      plotOptions: {
        gauge: {
          animation: false,
          pivot: {
            backgroundColor: "transparent"
          },
          dial: {
            backgroundColor: "transparent",
            baseWidth: 0,
          },
        }
      },

      yAxis: {
        min: 0,
        max: 100,
        minorTickInterval: 0,
        tickColor: "#ffffff",
        tickLength: 40,
        tickPixelInterval: 40,
        tickWidth: 0,
        lineWidth: 0,
        title: {
          text: opts.yAxis.title,
          style: {
            color: "#000000",
            fontFamily: "NicoPups",
            fontSize: "16px"
          }
        },
        labels: {
          ...opts.labels,
          style: {
            fontSize: "16px"
          }
        },
        plotBands: [{
          from: 1,
          to: score,
          color: {
            pattern: {
              image: "https://usetrmnl.com/images/grayscale/gray-2.png",
              width: 12,
              height: 12
            }
          },
          innerRadius: "82%",
          borderRadius: "50%"
        }, {
          from: score + 1,
          to: 100,
          color: {
            pattern: {
              image: "https://usetrmnl.com/images/grayscale/gray-5.png",
              width: 12,
              height: 12
            }
          },
          innerRadius: "82%",
          borderRadius: "50%",
        }]
      },

      series: [{
        name: "Score",
        data: [score],
        dataLabels: {
          borderWidth: 0,
          style: {
            fontSize: opts.series.fontSize,
            fontWeight: opts.series.fontWeight || "400",
            fontFamily: opts.series.fontFamily || "inherit"
          }
        }
      }],

      credits: {
        enabled: false
      }
    });
  }

  function textRating(score) {
    if (score <= 50) {
      return "Low";
    } else if (score <= 65) {
      return "Pay Attention";
    } else if (score < 80) {
      return "Fair";
    } else {
      return "Good";
    }
  }

  // Create small daily gauges
  dailyScores.forEach((score, idx) => {
    let opts = {
      title: null,
      labels: { enabled: false },
      series: {
        fontSize: "16px",
        fontWeight: "400",
        fontFamily: "NicoClean"
      },
      yAxis: {
        title: null
      }
    }
    createGauge(score, idx, opts);
  });

  // Create main weekly gauge
  createGauge(weeklyScore, "all", {
    title: null,
    height: "80%",
    labels: {
      distance: 15
    },
    series: {
      fontSize: "3em",
      fontWeight: "550"
    },
    yAxis: {
      title: textRating(weeklyScore)
    }
  });
</script>