# Sparkline

> A React sparkline: a word-sized chart for table cells, list rows, KPI tiles and running text, as a line, an area, bars or win / loss ticks.

- Type: React chart component (Charts & Stats)
- Access: Pro (the source needs a Wingo UI Pro plan, see https://wingo-ui.com/pricing)
- Version: 1.0.0
- Install: `npx wingo-ui@latest add sparkline`
- Docs: https://wingo-ui.com/components/sparkline

## Interaction

Read-only by default: the line draws in from the left the first time it scrolls into view and the last point pops in as a dot; screen readers hear the label and a summary ("from $8,200 to $12,480, +52.2%"). With interactive on, the sparkline becomes one tab stop: hover it with a mouse, or tap and drag sideways with a finger (vertical drags still scroll the page), and a compact readout above it shows the point's label and value while a hairline and a dot follow. The whole row height (8px above and below) is the touch target, a second tap on the same point or a tap outside clears it. From the keyboard, Tab focuses it, Left / Right walk the points, Home / End jump to the ends, Page Up / Page Down move by 10, Escape clears, and a polite live region reads each point. When the data changes the line and bars glide to their new shape. Reduced motion shows everything at once.

## Installation

```bash
npx wingo-ui@latest add sparkline
```

Pro item: run `npx wingo-ui@latest login` once with a Pro account. The CLI adds the files, their dependencies and a version record for updates.

With shadcn: `npx shadcn@latest add @wingo-ui/sparkline` (needs the @wingo-ui registry with your API key in components.json)

Files:

- `components/ui/sparkline.tsx`

npm dependencies: `npm i motion d3-shape d3-scale && npm i -D @types/d3-shape @types/d3-scale`

Wingo UI dependencies (installed automatically):

- [Chart kit](https://wingo-ui.com/components/chart-kit) ([Markdown](https://wingo-ui.com/components/chart-kit.md))
- [Trend badge](https://wingo-ui.com/components/trend-badge) ([Markdown](https://wingo-ui.com/components/trend-badge.md))
- [useControllableState](https://wingo-ui.com/components/use-controllable-state) ([Markdown](https://wingo-ui.com/components/use-controllable-state.md))
- [useLocale](https://wingo-ui.com/components/use-locale) ([Markdown](https://wingo-ui.com/components/use-locale.md))
- [Motion presets](https://wingo-ui.com/components/motion) ([Markdown](https://wingo-ui.com/components/motion.md))
- [Number format](https://wingo-ui.com/components/number-format) ([Markdown](https://wingo-ui.com/components/number-format.md))
- [Tones](https://wingo-ui.com/components/tones) ([Markdown](https://wingo-ui.com/components/tones.md))
- [UIProvider](https://wingo-ui.com/components/ui-config) ([Markdown](https://wingo-ui.com/components/ui-config.md))

## Usage

```tsx
import { Sparkline, SparklineWithValue } from "@/components/ui/sparkline"

const revenue = [8200, 8650, 8400, 9100, 9480, 9230, 10150, 10600, 10380, 11420, 11900, 12480]

export function ClientRow() {
  return (
    <div className="flex items-center justify-between gap-3">
      <span className="text-sm font-medium">Tech Solutions Inc.</span>
      <Sparkline
        data={revenue}
        valueFormat="currency"
        locale="en-US"
        label="Revenue, last 12 weeks"
        interactive
      />
      <SparklineWithValue
        data={revenue}
        type="area"
        valueFormat="currency"
        locale="en-US"
        layout="responsive"
        min={0}
        max={16000}
      />
    </div>
  )
}
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `data` | `(number \| null)[] \| { value: number \| null; label?: string; date?: string }[]` |  | The values, oldest first. Rows can carry a label ("Week 39") or an iso date for the readout; null leaves a gap in the line. |
| `type?` | `"line" \| "area" \| "bar" \| "win-loss"` | `"line"` | line, line over a soft fading fill, bars from zero, or win-loss: equal ticks up for positive and down for negative values (streaks, daily goals). Bars fall back to a line above 120 points. |
| `width?` | `number` | `96` | Width in px. 0 fills the container (the parent needs a width, e.g. a grid cell or a flex-1 box). |
| `height?` | `number` | `28` | Height in px. 28 reads well in a phone row; 16 sits inside a line of text. |
| `tone?` | `"neutral" \| "brand" \| "success" \| "warning" \| "danger" \| "info"` | `"neutral"` | The stroke and fill color. neutral is the ink (black in light mode, white in dark mode). |
| `color?` | `string` | `""` | Any CSS color, a palette slot ("series-3") or a tone name. Replaces tone and trendColor. |
| `trendColor?` | `boolean` | `false` | Color by the direction from the first to the last value: success when it rose, danger when it fell, the ink when flat. Win-loss paints wins green and losses red. |
| `invertTrend?` | `boolean` | `false` | Down is good (costs, churn, response time): a fall turns green under trendColor and reads as positive (data-intent). |
| `curve?` | `"monotone" \| "linear" \| "natural" \| "step"` | `"monotone"` | How the line joins the points. monotone never overshoots a value; step suits counts that jump. |
| `strokeWidth?` | `number` | `1.5` | Line width in px, with round caps and joins. |
| `showLast?` | `boolean` | `true` | A 5px dot on the last point, ringed in the surface color. For bars, the last bar keeps the full color and the others soften. |
| `showMinMax?` | `boolean` | `false` | Small hollow dots at the lowest and the highest point (bars: those bars in full color). |
| `reference?` | `"none" \| "first" \| "average" \| "zero"` | `"none"` | A dashed hairline at the first value, the average or zero (zero widens the range to include it). |
| `surface?` | `string` | `""` | The color behind the sparkline, used for the rings around dots. Empty is the surface token. |
| `min?` | `number` |  | Lower bound of the value range; the data's minimum when unset. Share min and max across the rows of a table so the sparklines compare. |
| `max?` | `number` |  | Upper bound of the value range; the data's maximum when unset. The Clients table example shares one range across rows. |
| `interactive?` | `boolean` | `false` | Focusable and inspectable: hover, tap, drag or arrow keys show each point in a compact readout pinned above the sparkline. |
| `activeIndex?` | `number \| null` |  | The inspected point, controlled (with onActiveIndexChange), so a value next to the sparkline can follow the scrub. |
| `defaultActiveIndex?` | `number \| null` | `"null"` | The inspected point on mount, uncontrolled; null starts with no readout. Needs interactive. |
| `onActiveIndexChange?` | `(index: number \| null) => void` |  | Called when a point is inspected or the readout clears. |
| `valueFormat?` | `ChartValueFormat = "number" \| "compact" \| "currency" \| "percent"` | `"number"` | How values print in the readout and the accessible summary ("$12,480" with currency and en-US). |
| `currency?` | `string` | `"USD"` | ISO 4217 code for valueFormat="currency", printed with its narrow symbol. |
| `formatValue?` | `(value: number, context: "tooltip" \| "label" \| "value") => string` |  | Full control over printed values, e.g. v => `${v} orders`. |
| `locale?` | `string` | `""` | Intl locale for values and dates. Empty follows the UIProvider, then the page. |
| `label?` | `string` | `""` | The accessible name, e.g. "Revenue, last 12 weeks". A summary of the first and last value and the change is appended. |
| `animated?` | `boolean` | `true` | Draws in the first time it scrolls into view (0.6s), the last dot pops in after it; data changes glide either way. Off under reduced motion. |
| `labels?` | `{ summary?: (first: string, last: string, change: string) => string; empty?: string; point?: (index: number, count: number) => string; inspectHint?: string }` |  | Screen reader strings. Defaults "from {first} to {last}, {change}", "No data", "{n} of {count}" and the arrow-key hint. Pass only the keys you translate. |
| `classNames?` | `Partial<Record<"svg" \| "line" \| "area" \| "bar" \| "last" \| "reference" \| "tooltip", string>>` |  | Extra classes for the inner parts. |
| `className?` | `string` |  | Extra classes for the root, e.g. "align-[-0.2em]" inside text. Other props (id, data-*, aria-*, events) spread onto the root span. |

## Parts

### DEFAULT_SPARKLINE_LABELS (constant)

The English screen reader strings: the summary "from {first} to {last}, {change}", "No data", "{n} of {count}" and the arrow-key hint.

### SparklineWithValue (component)

A sparkline with the current value and a TrendBadge, for table cells and list rows. value = the last point (the inspected point while scrubbing); delta = the % change first -> last (with deltaFormat "number" / "currency": last - first); deltaFormat = "percent"; badgeVariant = "ghost"; badgeSize = "sm"; showDelta = true; layout "inline" (default) | "stacked" (value and badge over the sparkline) | "responsive" (stacked below 640px); badgeLabels for the badge's spoken text; classNames { sparkline, value, badge, meta, ...the Sparkline slots }. className and style go to the wrapper, every other prop to the Sparkline, and activeIndex / onActiveIndexChange work the same. Props: SparklineWithValueProps.

## Examples

- **Clients table**: SparklineWithValue with shared min / max so rows compare; stacked under the value on phones.
- **Types**: line, area, bar and win-loss, filling their tiles (width 0).
- **Trend colors**: trendColor paints by direction; invertTrend makes falling costs green and rising returns red.
- **Inside text**: 64 x 16 sparklines on the text baseline (align-[-0.2em]).
- **Scrub to read**: interactive, reference="average" and min / max dots; the big number follows activeIndex.
- **KPI card footer**: type="area" at 48px filling the card, inspectable.
- **Live data**: Data updates glide on a smooth spring instead of redrawing.
- **Edge cases**: One value, all equal, gaps, no data, negatives and 365 points.

## See also

- [Chart kit](https://wingo-ui.com/components/chart-kit) ([Markdown](https://wingo-ui.com/components/chart-kit.md))
- [Trend badge](https://wingo-ui.com/components/trend-badge) ([Markdown](https://wingo-ui.com/components/trend-badge.md))
- [Line chart](https://wingo-ui.com/components/line-chart) ([Markdown](https://wingo-ui.com/components/line-chart.md))
- [Animated Counter](https://wingo-ui.com/components/animated-counter) ([Markdown](https://wingo-ui.com/components/animated-counter.md))
- [Stat Card](https://wingo-ui.com/components/stat-card) ([Markdown](https://wingo-ui.com/components/stat-card.md))

---

Canonical: https://wingo-ui.com/components/sparkline
More components: https://wingo-ui.com/components · Index for agents: https://wingo-ui.com/llms.txt
