Skip to content
microcharts
ReferenceDecisionStreakSpark

StreakSpark

StreakSpark collapses a run of pass/fail outcomes into bars whose width is run length, with a tick on the record.

encodes
width = run length; height + opacity = run type; current run accented
precision
high
nodes
1 rect per run, cap 40

StreakSpark collapses a sequence of pass/fail outcomes 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 accent bar at the right. The record streak carries a small triangle tick, so "are we near our best" reads without counting. Height and opacity encode run type, never magnitude, which leaves width as the only channel answering how long a run is.

StreakSpark
interactive · 5.14 kB · static · 2.81 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

Use it for pass/fail run histories, uptime and incident-free streaks, and the current run against a record. A continuous magnitude belongs in SparkBar and a single completion ratio in 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 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

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