Source: https://monarchui.dev/components/sparkline/

Components · Charts

# Sparkline

A word-sized trend line, area or sparkbar for tables, stat cards and lists, with gaps, invert, thresholds and a text alternative.

@rookcom/monarch-react/charts

Component

## Line, area and sparkbar

## Usage examples

### In table rows: thresholds, gaps and an inverted rank

### Responsive and not enough data

## Purpose

Shows the shape of a recent trend in the space of a word, next to the number it belongs to, without axes or interaction.

### Use when

- A trend column in a table (14-day latency per endpoint, rank history per keyword).
- A stat card or list row that needs "going up or down" at a glance.

### Avoid when

- Readers need exact values, axes or comparison between series: use LineChart.
- The trend is the main content of a section: use LineChart in a ChartFrame.

## Design principles

- The number leads; the sparkline supports it. Show the value or delta in text beside it.
- Gaps break the line, so missing data never looks like a trend.
- Tone carries meaning only with words: thresholds add "Warning" or "Critical" to the text alternative.
- No axes, labels or tooltips: when you need them, it is a LineChart.

## API reference

```tsx
import { Sparkline } from '@rookcom/monarch-react/charts';
```

| Export | Kind | Rendering | Root class |
| --- | --- | --- | --- |
| `Sparkline` | component | client | `.mn-sparkline` |

Renders a `<span>` (ref to it) holding an `aria-hidden` SVG; HTML attributes pass through.

With `label` the span is `role="img"` with a generated "latest, low, high" summary (or `summary`); without it the sparkline is decorative.

Fewer than two values (one for `bar`) show "Not enough data" (`labels.notEnoughData`) instead of a drawing.

Generated from the TypeScript declarations of `packages/react/src/components/charts/sparkline`.

## Properties

### `Sparkline`

A word-sized trend line, area or sparkbar for tables, stat cards and lists. Gaps break the line, `invert` suits ranks, thresholds set the tone, and a `label` turns it into an image with a min / max / latest summary.

| Prop | Type | Description |
| --- | --- | --- |
| `values` required | `readonly (number \| null)[]` | Values in order. `null` (or a non-finite number) is a gap: the line breaks there. |
| `className` | `string` |  |
| `color` | `ChartColor` | A series colour instead of a tone, to match a series in a nearby chart. |
| `domain` | `readonly [ChartDomainBound, ChartDomainBound]` | Fix the value range, so sparklines in a table share one scale. Default: each fits its own values. |
| `formatValue` | `ValueFormatter` | Formats the summary numbers. Wins over `valueFormat`. |
| `height` | `number` | Height in px. Default 24. |
| `id` | `string` |  |
| `invert` | `boolean` | Lower is better (a rank): smaller values are drawn higher. |
| `label` | `string` | Accessible name, such as "p95 latency, last 14 days". With it the sparkline is an image whose text alternative gives the latest, low and high values; without it the sparkline is decorative (`aria-hidden`), so put the numbers in text nearby. |
| `labels` | `SparklineLabels` |  |
| `locale` | `string` | BCP 47 locale for the summary numbers. |
| `markers` | `SparklineMarkers` | Dots on `last` (default) point, `all` points or `none`. Lone points between gaps always get one. |
| `responsive` | `boolean` | Stretch to the container's width; the stroke keeps its thickness. |
| `summary` | `string` | Replaces the generated text alternative (needs `label`). |
| `thresholds` | `SparklineThresholds` | Picks the tone from the latest value (wins over `tone`); the summary names the state. |
| `tone` | `SparklineTone` | Colour with meaning: `current` (default, inherits text colour), `neutral`, `accent`, `success`, `warning`, `danger`. Never the only signal: show the value or delta beside it. Exposed as `data-tone`. |
| `valueFormat` | `Intl.NumberFormatOptions` | `Intl.NumberFormat` options for the summary numbers. |
| `variant` | `SparklineVariant` | `line` (default), `area` (line plus soft fill) or `bar` (a sparkbar). Exposed as `data-variant`. |
| `width` | `number` | Width in px. Ignored with `responsive`. Default 80. |

## Variants

| Prop | Values | Description |
| --- | --- | --- |
| `variant` | `'line'``'area'``'bar'` | Line, line with a soft fill, or a sparkbar. `data-variant`. |
| `tone` | `'current'``'neutral'``'accent'``'success'``'warning'``'danger'` | `current` (default) inherits the text colour. `data-tone`. |
| `color` | `'1'``'2'``'3'``'4'``'5'``'neutral'` | A data palette slot, to match a series elsewhere. Wins over `tone`. |
| `markers` | `'last'``'all'``'none'` | Dots on the latest point (default), every point or none. |
| `invert` | `'true'``'false'` | Smaller values drawn higher, for ranks where lower is better. |
| `responsive` | `'true'``'false'` | Fills the container width with a constant stroke width. `data-responsive`. |

## States

| State | Exposed as | Behaviour |
| --- | --- | --- |
| Decorative | `aria-hidden="true"` | No `label`: hidden from assistive technology. |
| Labelled | `role="img"` | With `label`: an image with a text summary. |
| Threshold tone | `data-tone="warning" \| "danger"` | The latest value crossed `thresholds`; the summary names the state. |
| Not enough data | `data-empty` | A short muted text instead of the drawing. |

## Interaction behaviour

Not interactive. Put the sparkline inside a link or row if the trend should open details.

## Keyboard support

Not focusable: it has no interaction of its own.

## Accessibility

Role

img (with

label

), otherwise hidden

Accessible name

label

, followed by the generated summary: "p95 latency: latest 410 ms, low 180 ms, high 410 ms. Critical".

- Without a `label` the sparkline is `aria-hidden`; make sure the same information is in nearby text.
- Summary numbers use `Intl.NumberFormat` with `locale` and `valueFormat`, or `formatValue`.
- Threshold state is spelled out in the summary, not left to colour.
- Translate every word through `labels` (summary template, Warning, Critical, Not enough data).

## Responsive behaviour

- Fixed size by default (80 × 24); `responsive` stretches to the container and redraws at its measured width.
- The stroke keeps its width when stretched (`vector-effect: non-scaling-stroke`).

## Theme support

- Tones use the intent `strong` tokens and `--mn-color-text-subtle`; slots use `--mn-color-data-*`. All follow light, dark and high contrast.
- No animation.

## Do and don't

### Do

- Show the current value or delta as text next to the sparkline.
- Give sparklines in one table a shared `domain` when rows should be compared.
- Pass `label` when the sparkline is the only place the trend appears.

### Don't

- Rely on a green or red line alone to say good or bad.
- Use a sparkline where people need exact values; use LineChart.

## Related components

- [LineChart](https://monarchui.dev/components/line-chart/): The full chart with axes, tooltip and table.
- [StatCard](https://monarchui.dev/components/stat-card/): A headline number that can carry a sparkline.
- [DeltaIndicator](https://monarchui.dev/components/delta-indicator/): The change as text with direction, next to the sparkline.
- [DataTable](https://monarchui.dev/components/data-table/): Tables are the most common home for sparklines.

## Dependencies

| Kind | Depends on |
| --- | --- |
| npm packages | `react` |
| Monarch components | None |

Paths, scales and palette come from `src/internal/charts`.

## Testing coverage

- Decorative by default (aria-hidden, last-point marker); no axe violations.
- With `label`: role img and a locale-formatted latest / low / high summary.
- Thresholds above and below set the tone and name the state.
- Gaps split the line; lone points get a dot.
- `invert` flips the drawing; a fixed `domain` positions values on the shared scale.
- Sparkbar and area variants.
- Not enough data shows text (with the label for screen readers) and no SVG.
- Palette slot, responsive width and ref forwarding.
- Renders on the server.

| Check | Covered |
| --- | --- |
| Axe in jsdom | Yes |
| Server rendering | Yes |
| Browser suites | Visual baselines: /__gallery/sparkline; Cross-browser axe: /components/sparkline |

Tests: `packages/react/src/components/charts/sparkline`

## All example code

### Line, area and sparkbar

```tsx
import { Sparkline } from '@rookcom/monarch-react/charts';

const VISITS = [32, 41, 38, 45, 52, 49, 61, 58, 66, 72];

<Sparkline values={VISITS} />
<Sparkline values={VISITS} variant="area" color={1} />
<Sparkline values={VISITS} variant="bar" color={2} />
```

### In table rows: thresholds, gaps and an inverted rank

```tsx
import { Sparkline } from '@rookcom/monarch-react/charts';

const LATENCY = [180, 190, 210, null, 240, 260, 320, 410];

const RANK = [14, 12, 12, 9, 7, 8, 5, 4];

const ROW = { display: 'flex', alignItems: 'center', gap: 12, fontSize: 14 } as const;

<div style={ROW}>
  <span>GET /search</span>
  <Sparkline
    values={LATENCY}
    label="p95 latency, last 8 days"
    thresholds={{ warning: 300, danger: 400 }}
    formatValue={(v) => `${v} ms`}
  />
  <span>410 ms</span>
</div>
<div style={ROW}>
  <span>“project tracker”</span>
  <Sparkline values={RANK} invert label="Rank, last 8 weeks" color={1} />
  <span>#4</span>
</div>
```

### Responsive and not enough data

```tsx
import { Sparkline } from '@rookcom/monarch-react/charts';

const VISITS = [32, 41, 38, 45, 52, 49, 61, 58, 66, 72];

<Sparkline values={VISITS} variant="area" responsive height={40} color={3} />
<Sparkline values={[12]} label="Score" />
```
