Slope
React slope chart — who rose and who fell between two moments, crossings readable at a glance. Tiny accessible SVG microchart; RSC-safe static or /interactive.
Slope answers "who rose and who fell between two moments — and did the order change?". Lines stay neutral until you
declare positive: a rank change is not automatically good or bad. Both columns share one y-domain — per-column
normalization would fake convergence.
Install
import { Slope } from "@microcharts/react/slope";// cohorts — real values under “Sample data” below<Slope data={cohorts} title="Before vs after" />Sample data
const cohorts = [ { label: "East", from: 40, to: 47 }, { label: "West", from: 55, to: 41 }, { label: "South", from: 30, to: 33 }, { label: "North", from: 50, to: 44 }, { label: "Mid", from: 20, to: 35 },];Try it
When to use it
- Good for — before/after experiments, rank shuffles, two-moment comparisons.
- Avoid for — the path between the moments (Sparkline) or more than 7 categories.
Sizing
Variants
Edge cases
A row missing one side (from or to as NaN) draws a short dashed stub toward the end it does have, rather than a
full line — there's no second point to connect to, so nothing is interpolated. With a locale, both column labels and
the announced values follow that locale's own grouping.
Four homes
Why this default
A two-point line implies nothing about the path between — the docs steer to Sparkline when the journey matters. End labels drop deterministically, never by measurement: when the rows are denser than the label font (height ÷ count), and when the reserved label gutters would squeeze the two columns under ~35% of the width — in which case the reclaimed room goes back to the lines. Endpoints that would collide inside a column are nudged apart to a full glyph pitch instead of overlapping. A missing end renders a dashed stub and is announced "incomplete", never interpolated.
Accessibility
The accessible name counts directions and leads with the biggest mover — "3 categories: 2 up, 1 down. Largest change Mid, up 75%." The interactive entry finds the nearest line under the pointer and roves categories ordered by their after-value, announcing each slope ("East: 40 to 47, up 18%.").
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
| Prop | Type | Notes |
|---|---|---|
| data* | { label; from; to }[] | Two aligned moments per category. |
| label | "none" | "value" | "label" | "both" | End labels; dropped deterministically when rows collide. |
| highlight | number | string | The one-vs-field editorial read. |
| positive | "up" | "down" | Direction valence; unset = neutral ink. |
| animate | boolean | interactiveOpt-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
PairedBars
React paired bars chart — two related magnitudes side by side from zero. Tiny accessible SVG microchart; RSC-safe static or /interactive.
MicroScatter
React micro scatter chart — 2-D scatter with honest Pearson r in the summary. Tiny accessible SVG microchart; RSC-safe static or /interactive.