# Sparkline
URL: /diagrammatic/docs/charts/sparkline

A line the size of a word, for sentences, table cells, and KPI tiles.

> For AI agents: a documentation index is available at [llms.txt](/llms.txt). Use `.md` for canonical markdown pages; `.mdx` is kept as a backwards-compatible alias on supported URL paths.

```tsx
import { Sparkline } from "diagrammatic";

const METRICS = [
  {
    name: "Revenue",
    value: "$48.2k",
    delta: "+12.4%",
    data: [31, 33, 32, 36, 38, 37, 41, 43, 42, 46, 47, 48],
  },
  {
    name: "Signups",
    value: "1,284",
    delta: "+8.1%",
    data: [80, 92, 88, 97, 104, 99, 110, 118, 112, 121, 126, 131],
  },
  {
    name: "Open incidents",
    value: "3",
    delta: "-2",
    data: [6, 5, 7, 6, 4, 5, 5, 4, 3, 4, 3, 3],
  },
];

export default function KpiTiles() {
  return (
    <div data-dg-motion="" className="grid gap-3 sm:grid-cols-3">
      {METRICS.map((metric) => (
        <div key={metric.name} className="rounded-lg border p-4">
          <div className="text-muted-foreground text-xs">{metric.name}</div>
          <div className="mt-1 flex items-baseline gap-2">
            <span className="text-2xl font-medium tabular-nums">
              {metric.value}
            </span>
            <span className="text-muted-foreground text-xs tabular-nums">
              {metric.delta}
            </span>
          </div>
          <Sparkline
            block
            fill
            height={40}
            data={metric.data}
            title={`${metric.name}, last 12 weeks`}
            className="mt-3"
          />
        </div>
      ))}
    </div>
  );
}
```

## Usage

```
import { Sparkline } from "diagrammatic";

<p>
  Signups climbed all week <Sparkline data={[12, 14, 13, 17, 21]} />.
</p>;
```

A sparkline shows shape, not values: there is no axis, and the dot marks the latest point. Print the number it summarizes beside it.

## Examples

### In a sentence

By default a sparkline is `1em` tall with an automatic width, so it sits on the line of text it is part of.

```tsx
import { Sparkline } from "diagrammatic";

export default function InlineSparkline() {
  return (
    <p className="text-base leading-relaxed">
      Signups climbed all week{" "}
      <Sparkline
        data={[12, 14, 13, 17, 21, 19, 24, 28, 27, 33]}
        title="Signups over ten days"
      />{" "}
      and closed at 33, while churn held flat{" "}
      <Sparkline
        data={[4, 5, 4, 4, 5, 4, 4, 5, 4, 4]}
        title="Churn over ten days"
      />
      .
    </p>
  );
}
```

### In a table

The same sizing makes it a table cell that follows the row's type.

```tsx
import { Sparkline } from "diagrammatic";

const SERVICES = [
  {
    name: "api",
    p95: [212, 220, 198, 240, 231, 260, 244, 238, 251, 229, 219, 205],
    now: 205,
  },
  {
    name: "auth",
    p95: [88, 90, 86, 94, 91, 97, 112, 140, 128, 99, 92, 90],
    now: 90,
  },
  {
    name: "search",
    p95: [340, 352, 361, 330, 318, 301, 296, 288, 276, 270, 262, 255],
    now: 255,
  },
  {
    name: "billing",
    p95: [150, 148, 151, 149, 160, 171, 182, 179, 190, 201, 214, 226],
    now: 226,
  },
];

export default function ServiceTable() {
  return (
    <table className="w-full text-sm">
      <thead className="text-muted-foreground text-left text-xs">
        <tr>
          <th className="pb-2 font-normal">Service</th>
          <th className="pb-2 font-normal">p95, last 12 hours</th>
          <th className="pb-2 text-right font-normal">Now</th>
        </tr>
      </thead>
      <tbody>
        {SERVICES.map((service) => (
          <tr key={service.name}>
            <td className="py-1.5 font-mono text-xs">{service.name}</td>
            <td className="py-1.5">
              <Sparkline data={service.p95} title={`${service.name} p95`} />
            </td>
            <td className="py-1.5 text-right tabular-nums">{service.now} ms</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}
```

### In a tile

`block` breaks out of the text line and fills the host's width; `height` sets its pixel height. The figure at the top of this page is three tiles built this way, with `fill` shading the area under the line.

### Sizes

It scales with the surrounding `font-size`. Pass `width` and `height` for a fixed pixel size.

```tsx
import { Sparkline } from "diagrammatic";

const DATA = [3, 5, 4, 7, 6, 9, 8, 11, 10, 13];

export default function SparklineSizes() {
  return (
    <div className="flex flex-col gap-3">
      <p className="text-xs">
        12px text <Sparkline data={DATA} />
      </p>
      <p className="text-base">
        16px text <Sparkline data={DATA} />
      </p>
      <p className="text-2xl">
        24px text <Sparkline data={DATA} />
      </p>
      <p className="text-sm">
        A fixed size <Sparkline data={DATA} width={120} height={32} />
      </p>
    </div>
  );
}
```

### Color

The line is the current text color at 60%, and the end dot and fill take `--dg-c1`.

```tsx
import type { CSSProperties } from "react";
import { Sparkline } from "diagrammatic";

const DATA = [9, 8, 10, 7, 6, 7, 5, 4, 5, 3];

export default function SparklineColor() {
  return (
    <p className="text-sm">
      The line follows the text color{" "}
      <span className="text-red-600 dark:text-red-400">
        <Sparkline data={DATA} fill />
      </span>{" "}
      and the end dot and fill follow{" "}
      <span style={{ "--dg-c1": "#059669" } as CSSProperties}>
        <Sparkline data={DATA} fill />
      </span>{" "}
      the first categorical token.
    </p>
  );
}
```

### Live

A sparkline is a pure function of `data`, so a live reading is a state update. `data-dg-motion` pulses the end dot to mark it live; see [Motion](/diagrammatic/docs/motion).

```tsx
"use client";

import { useEffect, useState } from "react";
import { Sparkline } from "diagrammatic";

export default function LiveSparkline() {
  const [data, setData] = useState(() =>
    Array.from({ length: 24 }, (_, i) => 20 + Math.sin(i / 3) * 6),
  );

  useEffect(() => {
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    let t = 0;
    const id = setInterval(() => {
      t += 1;
      setData((prev) => {
        const last = prev[prev.length - 1] ?? 20;
        const next = Math.max(
          4,
          Math.min(40, last + Math.sin(t * 1.7) * 3 + Math.cos(t / 5) * 2),
        );
        return [...prev.slice(1), next];
      });
    }, 800);
    return () => clearInterval(id);
  }, []);

  const current = Math.round(data[data.length - 1] ?? 0);
  return (
    <p data-dg-motion="" className="text-2xl font-medium tabular-nums">
      {current} req/s{" "}
      <Sparkline data={data} fill title="Requests per second, live" />
    </p>
  );
}
```

## When to use it

- **Use it for** trend at a glance next to the number it explains: KPI tiles, table rows, sentences.
- **Watch out** for reading values off it. It has no axis and no tooltip by design; when the values matter, use a [Line](/diagrammatic/docs/charts/line).

## Props

- `data`: `number[]` — The values, in order. The baseline is zero or the smallest value, whichever is lower.
- `fill`: `boolean` (default `false`) — Shades the area under the line.
- `block`: `boolean` (default `false`) — Fills the host's width instead of sitting inline.
- `width?`: `number` — A pixel width instead of the automatic one.
- `height?`: `number` — A pixel height instead of \`1em\`.
- `title?`: `string` — Names the sparkline for assistive technology.
- `summary?`: `string` — A sentence read after the title.