# Timeseries Chart

A line (and optional area) chart on TanStack Charts, themed by the chart tokens: grid and tooltip follow light and dark, and the deploy marker is a dashed rule so a before and after read at a glance.

Source page: https://sproutboat.com/ikada/components/timeseries-chart

## Installation
```sh
npx shadcn@latest add https://sproutboat.com/ikada/r/timeseries-chart.json
```
Or from the package: `import { TimeseriesChart } from "@sproutboat/ikada/charts";`
## Usage
```tsx
import { TimeseriesChart } from "@/components/ikada/timeseries-chart";

const start = Date.UTC(2026, 10, 4);
const data = Array.from({ length: 48 }, (_, i) => ({
  time: start + i * 3_600_000, // one point an hour
  value: 120 + Math.round(60 * Math.sin(i / 6)) + i * 2,
}));

<TimeseriesChart
  ariaLabel="Requests, last 48 hours"
  series={[{ id: "req", label: "Requests", data, area: true }]}
  deploy={{ time: start + 30 * 3_600_000, label: "Deploy" }}
/>
```
## Examples
### Requests

```tsx
const start = Date.UTC(2026, 10, 4);
const data = Array.from({ length: 48 }, (_, i) => ({
  time: start + i * 3_600_000, // one point an hour
  value: 120 + Math.round(60 * Math.sin(i / 6)) + i * 2,
}));

<TimeseriesChart
  aria-label="Requests, last 48 hours"
  series={[{ id: "req", label: "Requests", data }]}
  deploy={{ time: start + 30 * 3_600_000, label: "Deploy" }}
  height={220}
/>
```
### Two series
Colour tokens and a dashed line tell series apart without relying on hue alone.
```tsx
const start = Date.UTC(2026, 10, 4);
const data = Array.from({ length: 48 }, (_, i) => ({
  time: start + i * 3_600_000, // one point an hour
  value: 120 + Math.round(60 * Math.sin(i / 6)) + i * 2,
}));

<TimeseriesChart
  aria-label="Requests and errors, last 48 hours"
  series={[
    { id: "req", label: "Requests", data, area: true },
    {
      id: "err",
      label: "Errors",
      color: "errors",
      dashed: true,
      data: data.map((p) => ({ ...p, value: Math.round(p.value / 20) })),
    },
  ]}
  height={220}
/>
```
### No data

```tsx
<TimeseriesChart aria-label="Requests, last hour" series={[]} height={160} />
```
## Props
### TimeseriesChartProps

| Prop | Type | Description |
| --- | --- | --- |
| series | `readonly TimeseriesSeries[]` | The lines to draw: a label, a colour and the points of each. |
| deploy? | `DeployMarker \| readonly DeployMarker[]` | A dashed vertical rule with a label, in the `chart-deploy` color. |
| height? | `number` | Height in pixels. Default 210; the width fills the container. |
| yDomain? | `readonly [number, number]` | [min, max] of the value axis. Defaults to 0 up to the largest value, rounded up. |
| xDomain? | `readonly [number, number]` | Time range in ms [from, to]. Defaults to the span of the data. |
| formatTime? | `((time: number) => string)` | Formats x ticks and the tooltip heading. Defaults to clock times ("14:30") for epoch milliseconds spanning up to two days, dates ("Nov 5") beyond that, and plain numbers otherwise. |
| locale? | `string` | Number and date locale; defaults to the `LocaleProvider` value, else `en`. |
| emptyText? | `string` | Shown in place of the plot when no series has a point. Default `No data for this range`. |
| formatValue? | `((value: number) => string)` | Formats y ticks and tooltip values. Default `(value: number): string => formatNumber(value)`. |
| formatTick? | `((value: number) => string)` | Formats y axis ticks. Defaults to compact numbers (1.5K) with no unit, so labels stay narrow. |
| xTicks? | `number` | Approximate number of x ticks. Defaults to 5. |
| yTicks? | `number` | About how many value ticks to draw. Default 4. |
| className? | `string` | Classes merged onto the root element, after ikada's own. |
| aria-label? | `string` |  |
| ariaLabel? | `string` |  |
Source: https://github.com/baronunread/ikada/blob/main/src/charts/timeseries-chart.tsx
