Sparkline
A tiny, axis-less trend line sized to sit inline — in a StatCard, a table cell, or beside a heading. Decorative by default.
Visits 39K
Usage#
import { Sparkline } from "neelam-ui";
<Sparkline data={visits} className="h-6 w-24 text-emerald-600" />data is the series, oldest value first. Fewer than two points renders nothing.
Sizing and colour#
width and height set the SVG's coordinate space, not its rendered size —
they only fix the aspect ratio. The actual size comes from CSS, so size it with
className.
Colour comes from currentColor, the way lucide-react's icons work, so tint
it by setting text-* on the sparkline or any ancestor rather than through a
colour prop that would need re-theming for dark mode.
showEndPoint draws a filled dot on the most recent value — the "current period
in the accent" end marker.
Decorative by default#
A sparkline is nearly always a redundant restatement of a number written out
right beside it, so announcing it too would be noise. With no label it renders
aria-hidden.
Pass label for the rare standalone case, which switches it to
role="img" with that name:
<Sparkline data={visits} label="Visits trending up over the last twelve months" />A label is not a substitute for the data
A sentence describing a trend loses every actual value. Where the trend is
the content rather than a garnish, use Chart and
its dataTable, which gives the numbers to everyone.
Why it is hand-drawn#
A sparkline is a polyline through normalized points plus an optional dot — a few
lines of arithmetic. Pulling in a charting library for that would add a
dependency for something Chart already covers when a
real chart engine is warranted, and this library keeps its dependency count
where Calendar's hand-rolled date maths and
DataTable's lack of a headless-table dependency
already put it.
Keyboard#
| Key | Behaviour |
|---|---|
| Tab | Not focusable in either mode. There is nothing to interact with — for hoverable values, use a Chart. |
Accessibility#
aria-hiddenwith nolabel;role="img"with an accessible name when one is given. There is no in-between state where it is announced as an unlabelled graphic.currentColormeans it inherits whatever contrast the surrounding text has already been checked for.- Ten to fifteen points reads best. A denser series compresses into noise at this size, which is a legibility problem for everyone.
API reference#
| Prop | Type | Default |
|---|---|---|
datarequiredThe series, oldest value first. Fewer than two points renders nothing. | number[] | — |
heightCoordinate-space height. Defaults to `24`. | number | 24 |
labelAccessible name. Omit — the default — to render the sparkline decoratively (`aria-hidden`), which is correct whenever the number it trends is already stated next to it, as in `StatCard`. | string | — |
showEndPointDraws a filled dot on the most recent point, the "current period in the accent" end-marker. | boolean | false |
strokeWidthStroke width for `variant="line"`, in CSS pixels (it doesn't scale with the box). Defaults to `2`. | number | 2 |
variant | enum | line |
widthCoordinate-space width. The rendered size comes from CSS — this only sets the aspect ratio. Defaults to `96`. | number | 96 |
Also accepts every native <svg> attribute except children, width, and
height, which are taken over above.