Skip to content
microcharts
ReferenceDecisionStreakSpark

StreakSpark

React streak spark chart — consecutive outcomes as a compact streak spark. Tiny accessible SVG microchart; RSC-safe static or /interactive.

StreakSpark answers "how long is the current run, and how does it compare to the record?". A sequence of pass/fail outcomes collapses into runs — each run a bar whose width is its length on one shared scale. Streak runs sit low and translucent, breaks sit thin and saturated, and the current run is the loud accent bar at the right. The record streak wears a small triangle tick, so "are we near our best" reads without counting.

StreakSpark
interactive · 5 kB · static · 2.72 kB

Install

Import & usereact/streak-spark
import { StreakSpark } from "@microcharts/react/streak-spark";// 1 = passing build, 0 = failing build<StreakSpark  data={[1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1]}  title="Deploy streak"/>
Needs package + stylesheetSet up with AI

Try it

When to use it

  • Good for — pass/fail run histories, uptime and incident-free streaks, the current run against a record.
  • Avoid for — a continuous magnitude (SparkBar) or a single completion ratio (Progress).

Sizing

Variants

data accepts booleans, 0/1, or any numbers (they pass on > 0, or on >= threshold). A null is a gap: it breaks the run and starts a fresh one. Everything else is a prop.

both labels
positive down
numeric + threshold
locale

With a locale, the count label and the accessible summary follow that locale's own grouping — a 1,204-build streak reads "1.204" in German. The outcome words come from strings, so the whole summary localizes together.

Edge cases

single outcome

A lone outcome is one current run of length 1, and it is trivially its own record — the summary reads "Current run 1 passing, unbroken."

all failing

When nothing passes there is no completed streak: the strip is one saturated break run, no triangle tick, and the summary reads "Current run 5 failing; no completed streak."

Four homes

Why this default

Runs, not per-outcome ticks, because the decision is about length — "how long have we held" and "how does that compare to our best". Width encodes run length on one shared scale, so a wide bar is a genuinely long run and the eye compares them honestly. Height and opacity encode run type (streak, break, current) — never magnitude — so the ribbon never implies a size it doesn't have. The record tick and the accented current bar answer the two questions the raw list can't, at a glance.

Accessibility

The accessible name states the current run, the record, and how often the streak broke — "Current run 3 passing; record 9; broke 2 times." The interactive entry roves runs with ← →, announcing each run's length, outcome, and whether it is the record ("Run 3 of 5: 4 passing."). Direction is carried by height, opacity, and color together, never color alone.

The interactive entry follows the shared interaction contract: arrow keys rove between units on both axes, Home and End jump to the ends, and a click, tap, Enter or Space selects a unit — pinning its readout so it survives blur, until you select it again or press Escape. On touch, a tap pins and a drag scrubs.

Props

PropTypeNotes
data*(boolean | number | null)[]Outcomes; null is a gap that breaks the run. Numbers pass on > 0.
positive"up" | "down"Which outcome is the streak: pass (up) or fail (down).
thresholdnumberWith numeric data, values ≥ threshold pass.
label"current" | "both" | "none"Count labels: the current run, the record too, or neither.
titlestringAccessible name; joins the auto summary.
summarystring | falseOverride or disable the auto summary.
animatebooleaninteractiveOpt-in entrance motion when the chart mounts client-side — add import "@microcharts/react/motion" once. Inert on the server, on hydrated server HTML, and under prefers-reduced-motion.

Plus the shared grammar — data, domain, color, title, summary, format — and the layout props (width, height, className, style) that every chart accepts. Interactive entries also share animate and live, and — wherever a chart has more than one navigable unit — onActive, onSelect, selectedIndex and defaultSelectedIndex; and — wherever the chart shows a hover value — readout. See the shared grammar.

Related charts