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.
<script lang="ts">
import { TimeseriesChart, ChartPalette, type TimeseriesData } from "kumo-svelte/components/chart";
import { echarts } from "../chart-echarts";
const start = Date.UTC(2026, 0, 1, 0, 0, 0);
const timeseriesData: TimeseriesData[] = [
{
name: "Requests",
color: ChartPalette.categorical(0),
data: Array.from({ length: 12 }, (_, index) => [
start + index * 60 * 60 * 1000,
120 + index * 16 + Math.round(Math.sin(index) * 30),
]),
},
{
name: "Cached",
color: ChartPalette.categorical(4),
data: Array.from({ length: 12 }, (_, index) => [
start + index * 60 * 60 * 1000,
80 + index * 10 + Math.round(Math.cos(index) * 18),
]),
},
];
</script>
<TimeseriesChart {echarts} data={timeseriesData} height={300} yAxisTickFormat={(value) => `${value.toLocaleString()}`} />
Custom X-Axis Label Format
Use the xAxisTickFormat prop to control how x-axis tick labels are rendered. The formatter receives the raw timestamp in milliseconds and returns a display string.
<script lang="ts">
import { TimeseriesChart, ChartPalette, type TimeseriesData } from "kumo-svelte/components/chart";
import { echarts } from "../chart-echarts";
const start = Date.UTC(2026, 0, 1, 0, 0, 0);
const timeseriesData: TimeseriesData[] = [
{
name: "Requests",
color: ChartPalette.categorical(0),
data: Array.from({ length: 12 }, (_, index) => [
start + index * 60 * 60 * 1000,
120 + index * 16 + Math.round(Math.sin(index) * 30),
]),
},
{
name: "Cached",
color: ChartPalette.categorical(4),
data: Array.from({ length: 12 }, (_, index) => [
start + index * 60 * 60 * 1000,
80 + index * 10 + Math.round(Math.cos(index) * 18),
]),
},
];
</script>
<TimeseriesChart
{echarts}
data={timeseriesData}
height={300}
xAxisTickFormat={(value) => new Intl.DateTimeFormat("en", { hour: "numeric" }).format(value)}
/>
Gradient Fill
Set gradient to true to render a vertical gradient fill beneath each line series.
<script lang="ts">
import { TimeseriesChart, ChartPalette, type TimeseriesData } from "kumo-svelte/components/chart";
import { echarts } from "../chart-echarts";
const start = Date.UTC(2026, 0, 1, 0, 0, 0);
const timeseriesData: TimeseriesData[] = [
{
name: "Requests",
color: ChartPalette.categorical(0),
data: Array.from({ length: 12 }, (_, index) => [
start + index * 60 * 60 * 1000,
120 + index * 16 + Math.round(Math.sin(index) * 30),
]),
},
{
name: "Cached",
color: ChartPalette.categorical(4),
data: Array.from({ length: 12 }, (_, index) => [
start + index * 60 * 60 * 1000,
80 + index * 10 + Math.round(Math.cos(index) * 18),
]),
},
];
</script>
<TimeseriesChart {echarts} data={timeseriesData} height={300} gradient />
Incomplete Data
Use the incomplete prop to indicate regions where data may be incomplete or still being collected.
<script lang="ts">
import { TimeseriesChart, ChartPalette, type TimeseriesData } from "kumo-svelte/components/chart";
import { echarts } from "../chart-echarts";
const start = Date.UTC(2026, 0, 1, 0, 0, 0);
const timeseriesData: TimeseriesData[] = [
{
name: "Requests",
color: ChartPalette.categorical(0),
data: Array.from({ length: 12 }, (_, index) => [
start + index * 60 * 60 * 1000,
120 + index * 16 + Math.round(Math.sin(index) * 30),
]),
},
{
name: "Cached",
color: ChartPalette.categorical(4),
data: Array.from({ length: 12 }, (_, index) => [
start + index * 60 * 60 * 1000,
80 + index * 10 + Math.round(Math.cos(index) * 18),
]),
},
];
const firstSeries = timeseriesData[0];
const before = firstSeries.data[2]?.[0];
const after = firstSeries.data[9]?.[0];
</script>
<TimeseriesChart {echarts} data={timeseriesData} height={300} incomplete={{ before, after }} />
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.
Selected range: Drag across the chart
<script lang="ts">
import { TimeseriesChart, ChartPalette, type TimeseriesData } from "kumo-svelte/components/chart";
import { echarts } from "../chart-echarts";
const start = Date.UTC(2026, 0, 1, 0, 0, 0);
const timeseriesData: TimeseriesData[] = [
{
name: "Requests",
color: ChartPalette.categorical(0),
data: Array.from({ length: 12 }, (_, index) => [
start + index * 60 * 60 * 1000,
120 + index * 16 + Math.round(Math.sin(index) * 30),
]),
},
{
name: "Cached",
color: ChartPalette.categorical(4),
data: Array.from({ length: 12 }, (_, index) => [
start + index * 60 * 60 * 1000,
80 + index * 10 + Math.round(Math.cos(index) * 18),
]),
},
];
let range = $state("");
</script>
<div class="space-y-3">
<TimeseriesChart
{echarts}
data={timeseriesData}
height={300}
onTimeRangeChange={(from, to) => (range = `${new Date(from).toLocaleTimeString()} – ${new Date(to).toLocaleTimeString()}`)}
/>
<p class="text-sm text-kumo-subtle">Selected range: {range || "Drag across the chart"}</p>
</div>
Bar Chart
Set type="bar" to render series as stacked bars instead of lines.
<script lang="ts">
import { TimeseriesChart, ChartPalette, type TimeseriesData } from "kumo-svelte/components/chart";
import { echarts } from "../chart-echarts";
const start = Date.UTC(2026, 0, 1, 0, 0, 0);
const timeseriesData: TimeseriesData[] = [
{
name: "Requests",
color: ChartPalette.categorical(0),
data: Array.from({ length: 12 }, (_, index) => [
start + index * 60 * 60 * 1000,
120 + index * 16 + Math.round(Math.sin(index) * 30),
]),
},
{
name: "Cached",
color: ChartPalette.categorical(4),
data: Array.from({ length: 12 }, (_, index) => [
start + index * 60 * 60 * 1000,
80 + index * 10 + Math.round(Math.cos(index) * 18),
]),
},
];
</script>
<TimeseriesChart {echarts} data={timeseriesData} height={300} type="bar" />
Loading State
Set loading to true to display the loading treatment while data is being fetched.
<script lang="ts">
import { TimeseriesChart, ChartPalette, type TimeseriesData } from "kumo-svelte/components/chart";
import { echarts } from "../chart-echarts";
const start = Date.UTC(2026, 0, 1, 0, 0, 0);
const timeseriesData: TimeseriesData[] = [
{
name: "Requests",
color: ChartPalette.categorical(0),
data: Array.from({ length: 12 }, (_, index) => [
start + index * 60 * 60 * 1000,
120 + index * 16 + Math.round(Math.sin(index) * 30),
]),
},
{
name: "Cached",
color: ChartPalette.categorical(4),
data: Array.from({ length: 12 }, (_, index) => [
start + index * 60 * 60 * 1000,
80 + index * 10 + Math.round(Math.cos(index) * 18),
]),
},
];
</script>
<TimeseriesChart {echarts} data={timeseriesData} height={300} loading />
API Reference
| Prop | Type | Description |
|---|---|---|
echarts | typeof echarts | Registered ECharts module instance. |
data | TimeseriesData[] | Series data. |
type | "line" \| "bar" | Series rendering mode. |
height | number | Chart height in pixels. |
gradient | boolean | Adds area fill for line charts. |
incomplete | { before?: number; after?: number } | Marks incomplete line regions. |
loading | boolean | Shows loading state. |
onTimeRangeChange | (from: number, to: number) => void | Called when the user brushes a time range. |
xAxisTickFormat | (value: number) => string | Formats x-axis ticks. |
yAxisTickFormat | (value: number) => string | Formats y-axis ticks. |
tooltipValueFormat | (value: number) => string | Formats tooltip values. |