Timeseries Chart
@cloudflare/kumo

The timeseries chart is a specialized chart for displaying time-based data. Each data point is a tuple of [timestamp_in_ms, value].

Basic Line Chart

A simple line chart displaying multiple data series over time.

import { ChartPalette, TimeseriesChart } from "@cloudflare/kumo";
import * as echarts from "echarts/core";
import { useMemo } from "react";

/**
 * Basic line chart example showing simple time-based data visualization.
 */
export function BasicLineChartDemo() {
  const isDarkMode = useIsDarkMode();

  const data = useMemo(
    () => [
      {
        name: "Requests",
        data: buildSeriesData(0, 50, 60_000, 1),
        color: ChartPalette.semantic("Neutral", isDarkMode),
      },
      {
        name: "Errors",
        data: buildSeriesData(1, 50, 60_000, 0.3),
        color: ChartPalette.semantic("Attention", isDarkMode),
      },
    ],
    [isDarkMode],
  );

  return (
    <TimeseriesChart
      echarts={echarts}
      isDarkMode={isDarkMode}
      data={data}
      xAxisName="Time (UTC)"
      yAxisName="Count"
    />
  );
}

Custom X-Axis Label Format

Use the xAxisTickLabelFormat prop to control how x-axis tick labels are rendered. The formatter receives the raw timestamp in milliseconds and returns a display string, overriding ECharts’ built-in time formatting.

import { ChartPalette, TimeseriesChart } from "@cloudflare/kumo";
import * as echarts from "echarts/core";
import { useMemo } from "react";

/**
 * Timeseries chart with custom axis tick label formats for both x-axis (HH:MM) and y-axis (compact numbers).
 */
export function CustomAxisLabelFormatDemo() {
  const isDarkMode = useIsDarkMode();

  const data = useMemo(
    () => [
      {
        name: "Requests",
        data: buildSeriesData(0, 50, 60_000, 1000),
        color: ChartPalette.semantic("Neutral", isDarkMode),
      },
    ],
    [isDarkMode],
  );

  return (
    <TimeseriesChart
      echarts={echarts}
      isDarkMode={isDarkMode}
      data={data}
      xAxisName="Time (UTC)"
      yAxisName="Requests"
      xAxisTickFormat={(ts) => {
        const d = new Date(ts);
        return `${d.getHours().toString().padStart(2, "0")}:${d.getMinutes().toString().padStart(2, "0")}`;
      }}
      yAxisTickFormat={(value) => {
        if (value >= 1000) return `${value / 1000}k`;
        return value.toString();
      }}
      tooltipValueFormat={(value) => `${(value / 1000).toFixed(1)}k requests`}
    />
  );
}

Gradient Fill

Set gradient to true to render a vertical gradient fill beneath each line series. The fill fades from the series color at the top to transparent at the bottom, giving the chart a polished area-chart look without losing the clarity of individual lines.

import { ChartPalette, TimeseriesChart } from "@cloudflare/kumo";
import * as echarts from "echarts/core";
import { useMemo } from "react";

/**
 * Timeseries chart with gradient fill beneath each line series.
 */
export function GradientLineChartDemo() {
  const isDarkMode = useIsDarkMode();

  const data = useMemo(
    () => [
      {
        name: "Requests",
        data: buildSeriesData(0, 50, 60_000, 1),
        color: ChartPalette.semantic("Neutral", isDarkMode),
      },
      {
        name: "Errors",
        data: buildSeriesData(1, 50, 60_000, 0.3),
        color: ChartPalette.semantic("Attention", isDarkMode),
      },
    ],
    [isDarkMode],
  );

  return (
    <TimeseriesChart
      echarts={echarts}
      isDarkMode={isDarkMode}
      data={data}
      xAxisName="Time (UTC)"
      yAxisName="Count"
      gradient
    />
  );
}

Incomplete Data

Use the incomplete prop to indicate regions where data may be incomplete or still being collected.

import { ChartPalette, TimeseriesChart } from "@cloudflare/kumo";
import * as echarts from "echarts/core";
import { useMemo } from "react";

/**
 * Timeseries chart with incomplete data regions highlighted.
 */
export function IncompleteDataChartDemo() {
  const isDarkMode = useIsDarkMode();

  const data = useMemo(
    () => [
      {
        name: "Bandwidth",
        data: buildSeriesData(0, 50, 60_000, 1),
        color: ChartPalette.color(0, isDarkMode),
      },
    ],
    [isDarkMode],
  );

  const incompleteTimestamp = data[0].data[data[0].data.length - 5][0];

  return (
    <TimeseriesChart
      echarts={echarts}
      isDarkMode={isDarkMode}
      data={data}
      xAxisName="Time (UTC)"
      yAxisName="Mbps"
      incomplete={{ after: incompleteTimestamp }}
    />
  );
}

Time Range Selection

Enable time range selection by providing the onTimeRangeChange callback. Users can click and drag on the chart to select a time range.

import { ChartPalette, TimeseriesChart } from "@cloudflare/kumo";
import * as echarts from "echarts/core";
import { useMemo } from "react";

/**
 * Timeseries chart with time range selection enabled.
 */
export function TimeRangeSelectionChartDemo() {
  const isDarkMode = useIsDarkMode();

  const data = useMemo(
    () => [
      {
        name: "CPU Usage",
        data: buildSeriesData(0, 50, 60_000, 1),
        color: ChartPalette.color(0, isDarkMode),
      },
    ],
    [isDarkMode],
  );

  return (
    <TimeseriesChart
      echarts={echarts}
      isDarkMode={isDarkMode}
      data={data}
      xAxisName="Time (UTC)"
      yAxisName="%"
      onTimeRangeChange={(from, to) => {
        alert(
          `Selected range:\nFrom: ${new Date(from).toLocaleString()}\nTo: ${new Date(to).toLocaleString()}`,
        );
      }}
    />
  );
}

Bar Chart

Set type=β€œbar” to render series as stacked bars instead of lines. All other props β€” axes, tooltips, colors β€” work identically.

import { ChartPalette, TimeseriesChart } from "@cloudflare/kumo";
import * as echarts from "echarts/core";
import { useMemo } from "react";

/**
 * Timeseries chart rendered as a stacked bar chart.
 */
export function BarChartDemo() {
  const isDarkMode = useIsDarkMode();

  const data = useMemo(
    () => [
      {
        name: "Requests",
        data: buildSeriesData(0, 20, 3_600_000, 1),
        color: ChartPalette.semantic("Neutral", isDarkMode),
      },
      {
        name: "Errors",
        data: buildSeriesData(1, 20, 3_600_000, 0.3),
        color: ChartPalette.semantic("Attention", isDarkMode),
      },
    ],
    [isDarkMode],
  );

  return (
    <TimeseriesChart
      echarts={echarts}
      isDarkMode={isDarkMode}
      type="bar"
      data={data}
      xAxisName="Time (UTC)"
      yAxisName="Count"
    />
  );
}

Loading State

Set loading to true to display an animated sine-wave skeleton while data is being fetched. The chart canvas is hidden until loading completes; swap back to loading={false} to reveal the chart.

import { TimeseriesChart } from "@cloudflare/kumo";
import * as echarts from "echarts/core";

/**
 * Timeseries chart in loading state, showing the animated sine-wave skeleton.
 * Loads for 5 seconds then reveals the real chart. A button restarts the cycle.
 */
export function LoadingChartDemo() {
  const isDarkMode = useIsDarkMode();
  return (
    <div className="flex flex-col flex-1 w-full">
      <TimeseriesChart
        echarts={echarts}
        isDarkMode={isDarkMode}
        xAxisName="Time (UTC)"
        yAxisName="Count"
        data={[]}
        loading
      />
    </div>
  );
}