Real-Time Dashboard Tiles — Chart.js

A dashboard layout displaying multiple metric tiles in a responsive grid, where each tile shows a KPI value with its label, an embedded sparkline showing recent trend, and a change indicator (up/down arrow with percentage). This visualization is essential for operations monitoring and business dashboards where multiple metrics need to be tracked simultaneously at a glance. The combination of current value, trend visualization, and change direction provides comprehensive metric context in a compact format.

Real-Time Dashboard Tiles rendered with Chart.js

Renders

JavaScript source (Chart.js)

// anyplot.ai
// dashboard-metrics-tiles: Real-Time Dashboard Tiles
// Library: chartjs 4.4.7 | JavaScript 22.23.2
// Quality: 92/100 | Updated: 2026-09-02

const t = window.ANYPLOT_TOKENS;

// --- Data (in-memory, deterministic) ----------------------------------------
// Tiny fixed-seed LCG — the browser has no seeded RNG.
let seed = 42;
function rand() {
  seed = (seed * 1103515245 + 12345) & 0x7fffffff;
  return seed / 0x7fffffff;
}

// Builds a short trend history that drifts toward `drift` each step, then
// derives the tile's headline value from the trend's final point so the
// sparkline and the big number always agree.
function buildMetric(
  name,
  unit,
  decimals,
  base,
  spread,
  drift,
  points,
  changePercent,
  higherIsBetter,
  status,
) {
  const data = [];
  let v = base;
  for (let i = 0; i < points; i++) {
    v = Math.max(0, v + (rand() - 0.5) * spread + drift);
    data.push(v);
  }
  const value =
    decimals > 0
      ? +data[data.length - 1].toFixed(decimals)
      : Math.round(data[data.length - 1]);
  return { name, unit, value, data, changePercent, higherIsBetter, status };
}

const metrics = [
  buildMetric("CPU Usage", "%", 0, 50, 6, -0.35, 16, -5.2, false, "good"),
  buildMetric("Memory", "%", 0, 64, 5, 0.55, 16, 8.4, false, "warning"),
  buildMetric(
    "Response Time",
    "ms",
    0,
    140,
    12,
    -1.3,
    16,
    -15.3,
    false,
    "good",
  ),
  buildMetric(
    "Error Rate",
    "%",
    1,
    2.2,
    0.6,
    0.12,
    16,
    42.1,
    false,
    "critical",
  ),
  buildMetric("Requests/sec", "", 0, 1700, 90, 8, 16, 6.7, true, "good"),
  buildMetric("Active Users", "", 0, 9500, 220, -18, 16, -2.1, true, "warning"),
];

// good/warning/critical are a traffic-light convention readers already expect —
// semantic exception from the Imprint palette rather than ordinal position.
const STATUS_COLOR = {
  good: t.palette[0],
  warning: t.amber,
  critical: t.palette[4],
};

// null = flat (no favorable/unfavorable read); otherwise "does this change help".
function favorableColor(m) {
  if (m.changePercent === 0) return t.inkSoft;
  const favorable = m.changePercent > 0 === m.higherIsBetter;
  return favorable ? t.palette[0] : t.palette[4];
}

// Chart.js plugin: marks the sparkline's last point with a filled "now" dot,
// ringed in the card color so it reads clearly against the line/fill.
const endpointDotPlugin = {
  id: "endpointDot",
  afterDatasetsDraw(chart) {
    const meta = chart.getDatasetMeta(0);
    const point = meta.data[meta.data.length - 1];
    if (!point) return;
    const { ctx } = chart;
    ctx.save();
    ctx.beginPath();
    ctx.arc(point.x, point.y, 4, 0, Math.PI * 2);
    ctx.fillStyle = chart.data.datasets[0].borderColor;
    ctx.fill();
    ctx.lineWidth = 2;
    ctx.strokeStyle = t.elevatedBg;
    ctx.stroke();
    ctx.restore();
  },
};

// --- Mount -------------------------------------------------------------------
const root = document.getElementById("container");
root.style.display = "flex";
root.style.flexDirection = "column";
root.style.padding = "36px 44px 40px";
root.style.gap = "22px";

const heading = document.createElement("div");
heading.textContent =
  "dashboard-metrics-tiles · javascript · chartjs · anyplot.ai";
heading.style.fontSize = "22px";
heading.style.fontWeight = "600";
heading.style.color = t.ink;
root.appendChild(heading);

const grid = document.createElement("div");
grid.style.flex = "1";
grid.style.display = "grid";
grid.style.gridTemplateColumns = "repeat(3, 1fr)";
grid.style.gridTemplateRows = "repeat(2, 1fr)";
grid.style.gap = "22px";
root.appendChild(grid);

// --- Tiles ---------------------------------------------------------------
metrics.forEach((m) => {
  const tile = document.createElement("div");
  tile.style.background = t.elevatedBg;
  tile.style.borderRadius = "16px";
  tile.style.padding = "24px 28px";
  tile.style.display = "flex";
  tile.style.flexDirection = "column";
  tile.style.justifyContent = "center";
  tile.style.gap = "14px";
  grid.appendChild(tile);

  const labelRow = document.createElement("div");
  labelRow.style.display = "flex";
  labelRow.style.alignItems = "center";
  labelRow.style.gap = "10px";
  tile.appendChild(labelRow);

  const dot = document.createElement("span");
  dot.style.width = "11px";
  dot.style.height = "11px";
  dot.style.borderRadius = "50%";
  dot.style.background = STATUS_COLOR[m.status];
  dot.style.flex = "none";
  labelRow.appendChild(dot);

  const label = document.createElement("span");
  label.textContent = m.name;
  label.style.fontSize = "16px";
  label.style.fontWeight = "500";
  label.style.color = t.inkSoft;
  labelRow.appendChild(label);

  const valueRow = document.createElement("div");
  valueRow.style.display = "flex";
  valueRow.style.alignItems = "baseline";
  valueRow.style.gap = "14px";
  tile.appendChild(valueRow);

  const value = document.createElement("span");
  value.textContent = `${m.value}${m.unit}`;
  value.style.fontSize = "46px";
  value.style.fontWeight = "700";
  value.style.color = t.ink;
  valueRow.appendChild(value);

  const arrow = m.changePercent > 0 ? "▲" : m.changePercent < 0 ? "▼" : "–";
  const change = document.createElement("span");
  change.textContent = `${arrow} ${Math.abs(m.changePercent).toFixed(1)}%`;
  change.style.fontSize = "18px";
  change.style.fontWeight = "600";
  change.style.color = favorableColor(m);
  valueRow.appendChild(change);

  const sparkWrap = document.createElement("div");
  sparkWrap.style.height = "84px";
  tile.appendChild(sparkWrap);

  const canvas = document.createElement("canvas");
  sparkWrap.appendChild(canvas);

  new Chart(canvas, {
    type: "line",
    data: {
      labels: m.data.map((_, i) => i),
      datasets: [
        {
          data: m.data,
          borderColor: STATUS_COLOR[m.status],
          // Canvas gradient (fades to transparent) instead of a flat alpha
          // fill — a genuine canvas/Chart.js scriptable-option feature.
          backgroundColor: (ctx) => {
            const { chartArea, ctx: c } = ctx.chart;
            if (!chartArea) return `${STATUS_COLOR[m.status]}26`;
            const gradient = c.createLinearGradient(
              0,
              chartArea.top,
              0,
              chartArea.bottom,
            );
            gradient.addColorStop(0, `${STATUS_COLOR[m.status]}55`);
            gradient.addColorStop(1, `${STATUS_COLOR[m.status]}00`);
            return gradient;
          },
          borderWidth: 2.5,
          pointRadius: 0,
          fill: true,
          tension: 0.35,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      animation: false,
      // Room for the endpoint dot, which would otherwise clip against the
      // canvas edge since the last data point sits at the plot boundary.
      layout: { padding: { top: 5, right: 5, bottom: 5 } },
      plugins: { legend: { display: false }, tooltip: { enabled: false } },
      scales: { x: { display: false }, y: { display: false } },
    },
    plugins: [endpointDotPlugin],
  });
});

Retrieve this implementation

Runnable source as JSON, for any HTTP client: https://api.anyplot.ai/specs/dashboard-metrics-tiles/chartjs/code. Any spec id and library id listed in llms-full.txt fit the same URL shape; every URL below is complete and callable.

{
  "spec_id": "dashboard-metrics-tiles",
  "language": "javascript",
  "library": "chartjs",
  "page": "https://anyplot.ai/dashboard-metrics-tiles/javascript/chartjs",
  "hub": "https://anyplot.ai/dashboard-metrics-tiles",
  "code_json": "https://api.anyplot.ai/specs/dashboard-metrics-tiles/chartjs/code",
  "spec_json": "https://api.anyplot.ai/specs/dashboard-metrics-tiles",
  "render_light_png": "https://storage.googleapis.com/anyplot-images/plots/dashboard-metrics-tiles/javascript/chartjs/plot-light.png",
  "render_dark_png": "https://storage.googleapis.com/anyplot-images/plots/dashboard-metrics-tiles/javascript/chartjs/plot-dark.png",
  "interactive_light_html": "https://storage.googleapis.com/anyplot-images/plots/dashboard-metrics-tiles/javascript/chartjs/plot-light.html",
  "interactive_dark_html": "https://storage.googleapis.com/anyplot-images/plots/dashboard-metrics-tiles/javascript/chartjs/plot-dark.html",
  "quality_score": 92.0,
  "license": "MIT",
  "guide": "https://anyplot.ai/llms.txt"
}

Part of Real-Time Dashboard Tiles on anyplot.ai.

Other implementations