Sparkline
Dependency-free inline SVG trend line for tables and metric cards
Sparkline is a compact, axis-less line chart that sits next to a number and answers one question: which way is this going? Reach for it in queue tables, KPI headers, and account rows where a full chart would be noise but a bare number hides the trend.
It is the kit's chart primitive and needs no charting library — it renders plain inline SVG. Sparkline differs from Meter and Progress in what it plots: Meter reports a measurement inside a known range, Progress reports task completion, and Sparkline plots a series over time with no absolute scale of its own.
Import
import { Sparkline } from '@nim-ui/components';Playground
Edit the series, tone, and flags — the geometry recomputes from the data.
<div className="flex w-full max-w-md flex-col gap-4"> <Sparkline data={[12, 18, 15, 22, 27, 24, 31]} label="Orders, last 7 days" className="h-8 w-full" /> <Sparkline data={[48, 52, 44, 61, 58, 72, 80]} label="Revenue trend" tone="success" area showLastPoint className="h-10 w-full" /> <Sparkline data={[180, 210, 260, 240, 330, 410, 480]} label="p95 latency" tone="error" min={0} className="h-8 w-full" /> </div>
Tones
ink is the default and the right choice when the trend is neutral information. Reserve status tones for series an operator is meant to judge; steel reads as quiet interactive emphasis.
Code
const series = [12, 18, 15, 22, 27, 24, 31];
const falling = [31, 24, 27, 22, 15, 18, 12];
<Sparkline data={series} label="Neutral trend" className="h-8 w-full" />
<Sparkline data={series} label="Steel trend" tone="steel" className="h-8 w-full" />
<Sparkline data={series} label="Healthy trend" tone="success" className="h-8 w-full" />
<Sparkline data={falling} label="Degrading trend" tone="error" className="h-8 w-full" />Area and last point
area adds a soft fill under the line for standalone cards; showLastPoint marks the most recent reading so the eye lands on "now" rather than the peak.
Code
<Sparkline
data={[31, 34, 30, 38, 42, 40, 48]}
label="Gross volume, last 7 days"
tone="success"
area
showLastPoint
className="mt-1 h-12 w-full"
/>In a table row
At its intrinsic 120×32 size the line stays crisp beside dense numeric columns — the stroke does not scale with the box.
Code
<Sparkline data={[8, 11, 9, 14, 13, 18, 21]} label="Northwind Traders order trend" />
<Sparkline data={[24, 22, 25, 19, 16, 14, 9]} label="Contoso Ltd order trend" tone="error" />
<Sparkline data={[15, 15, 15, 15, 15, 15, 15]} label="Fabrikam Inc order trend" />Sparse and empty data
A flat series renders a centered flat line, a single reading renders a flat line across the box, and an empty series renders an accessible empty chart — never a broken or NaN path. An explicit min / max pins the domain so rows stay comparable, and either bound works on its own: pass min={0} alone to anchor the floor while the ceiling still tracks the data.
An empty chart carries data-empty="true" on the <svg>, so you can style or replace the empty state from CSS ([data-empty] { … }) without branching in your own render.
Code
<Sparkline data={[]} label="No activity recorded" className="h-8 w-full" />
<Sparkline data={[42]} label="Single reading" className="h-8 w-full" />
<Sparkline data={[15, 15, 15, 15]} label="Unchanged" className="h-8 w-full" />
<Sparkline data={[4, 6, 5, 7]} label="Pinned domain" min={0} max={20} tone="steel" className="h-8 w-full" />Props
| Name | Type | Default | Description |
|---|---|---|---|
data* | number[] | - | The series to plot, oldest first. Non-finite entries are ignored |
label* | string | - | Accessible name for the chart — describe the series and its window |
width | number | 120 | Intrinsic width in viewBox units; override the rendered size with className |
height | number | 32 | Intrinsic height in viewBox units; override the rendered size with className |
tone | 'ink' | 'steel' | 'success' | 'warning' | 'error' | 'ink' | Series color; ink for neutral trends, status tones for judged ones |
area | boolean | false | Draw a soft fill between the line and the baseline |
showLastPoint | boolean | false | Emphasize the most recent value with a dot |
strokeWidth | number | 1.5 | Line thickness in device pixels (the stroke does not scale with the box) |
min | number | - | Lower bound of the value domain; derived from data when omitted |
max | number | - | Upper bound of the value domain; derived from data when omitted |
className | string | - | Additional CSS classes to apply |
Accessibility
- Renders
role="img"witharia-label, so the chart is announced as a single named image rather than a pile of unlabeled shapes. labelis required — name the series and its window ("Orders, last 7 days"), since the chart has no visible axis or title.- A sparkline is a summary, not the data. Always pair it with the current value in text, and keep the underlying numbers reachable in a table or detail view.
- Tone alone must never carry the meaning — an operator with low color vision should get the same story from the shape and the adjacent number.
- Non-interactive by design: it takes no focus and needs none. If a trend must be actionable, wrap it in a Button or link that owns the focus ring.
Best Practices
Do
- Use Sparkline for a series over time; Meter for capacity, Progress for task completion
- Pass an explicit
min/maxwhen sparklines in the same column must be compared - Keep
inkas the default and save status tones for series an operator should judge - Stretch it with
className="h-8 w-full"in cards, and leave the intrinsic size in dense table rows - Enable
showLastPointwhen "the latest value" is the point, not the peak - Drop it into
MetricCardVisual— that slot exists for exactly this kind of visual
Don't
- Add axes, gridlines, or tooltips — that is a full chart, not a sparkline
- Use
areain table rows; the fill turns a scannable column into visual noise - Plot fewer than about five points, where the "trend" is mostly noise
- Let a sparkline be the only place a number appears
Related Components
- Meter - Capacity and usage within a known range
- MetricCard - KPI cards with a
MetricCardVisualslot for this - Stat - Single metric with trend indicator
- Progress - Task completion indicator