Sparkline

Show a compact trend beside a value.

datachart
Preview
Sparkline preview
Signups38+12.4%
Revenue42+35.5%
Churn15−8.2%

When to use

  • A compact trend inside a card, table row, or KPI tile.
  • Small charts people can scrub by pointer or keyboard to read past values.

When not to use

  • Use bar-chart for comparing discrete periods with axes.
  • Use stat-card or metric-card when only the latest value matters.

shadcn CLI

Also installs (1)

  • manicat-foundation
Manual install(+)
registry.jsonjson
{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "sparkline",
  "type": "registry:ui",
  "title": "Sparkline",
  "description": "Show a compact trend beside a value.",
  "categories": [
    "data"
  ],
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "https://manicat.viraza.net/r/manicat-foundation.json"
  ],
  "files": [
    {
      "path": "registry/components/sparkline/sparkline.tsx",
      "type": "registry:component",
      "target": "@components/manicat/sparkline/sparkline.tsx"
    },
    {
      "path": "registry/components/sparkline/sparkline.module.css",
      "type": "registry:component",
      "target": "@components/manicat/sparkline/sparkline.module.css"
    }
  ],
  "docs": "Docs and live preview: https://uiarc.dev/components/sparkline",
  "meta": {
    "tier": "free",
    "kind": "component",
    "docs": "https://manicat.viraza.net/components/sparkline",
    "markdown": "https://uiarc.dev/components/sparkline/markdown",
    "tags": [
      "data",
      "chart"
    ]
  }
}

Usage

Install the component, then copy this into your app. Change the content and the props to fit your screen.

example.tsxtsx
"use client";

import { Sparkline } from "@/components/manicat/sparkline/sparkline";

export function SparklineExample() {
  return (
    <div className="grid w-full max-w-md gap-4 sm:grid-cols-3">
      <Sparkline data={[12, 16, 14, 21, 18, 24, 29, 26, 33, 31, 38]} label="Signups" value="38" change="+12.4%" />
      <Sparkline data={[9, 13, 11, 17, 15, 22, 20, 27, 24, 31, 42]} label="Revenue" value="42" change="+35.5%" />
      <Sparkline data={[30, 28, 31, 26, 27, 24, 22, 23, 19, 18, 15]} label="Churn" value="15" change="−8.2%" tone="danger" />
    </div>
  );
}

Examples

Real screens rather than isolated props. Switch to Code to copy a whole example into your project.

KPI row Three KPI cards on a dashboard, each with its trend line and a delta against last week.

KPI row Three KPI cards on a dashboard, each with its trend line and a delta against last week. preview
Signups3,812+12.4%
MRR$42.1k+35.5%
Churn1.5%−8.2%

Keyboard interactions

KeysAction
ArrowLeft / ArrowRightMoves the cursor one point back or forward (ArrowDown and ArrowUp too).
PageDown / PageUpMoves about a sixth of the series.
Home / EndJumps to the first or last point.
EscapeStops scrubbing and returns to the latest value.

Accessibility

  • The figure has an aria-label describing the series; the SVG is hidden.
  • When interactive, the plot is a focusable role="slider" whose aria-valuetext reads the point label and value.
  • Pass labels so scrubbed points read as dates rather than positions.

Motion

  • The line draws in on first view and the end dot appears as it lands.
  • While scrubbing, the cursor springs between points, later points dim, and headline copy rolls.
  • Reduced motion shows the full line at once and moves the cursor without springing.

Responsive behavior

  • The plot measures its width with a ResizeObserver and redraws to fill its container.
  • Scrubbing uses touch-action pan-y, so a horizontal drag scrubs while vertical swipes still scroll the page.
  • On touch the readout returns to the latest value when the finger lifts.

Performance

  • Each chart has its own ResizeObservers and an in-view draw; set interactive to false in dense tables to drop tab stops and handlers.

Notes for AI

  • Use for a compact trend inside a card or table row. Use bar-chart for comparing discrete periods with axes.
  • Pass value as the formatted latest reading; formatValue should match it so scrubbed values look consistent.
  • Set interactive to false in dense tables to avoid many tab stops.