Slope
Slope connects each category's before and after value on one shared scale, so rises, falls, and crossings read directly.
- encodes
- line slope between two aligned columns
- precision
- medium-high
- nodes
- ≤ 3 per category (≤ 7)
- collection
- Core
Slope draws one line per category between two moments: East 40 to 47, West 55 to 41, and any crossing between them. Both
columns share one y-domain, since per-column normalization would fake convergence. Lines stay neutral until you declare
positive, because a rank change is not automatically good or bad.
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
- hover · rove · click…
Hover near a line or rove with ↑/↓ (ordered by the after value) — each announces its slope.
import { Slope } from "@microcharts/react/slope/interactive";// cohorts — real values under “Sample data” below<Slope data={cohorts}/>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 },];When to use it
Use it for before/after experiments, rank shuffles, and two-moment comparisons, up to about 7 categories. A two-point line says nothing about the path between the moments, so use Sparkline when that path is the point.
Sizing
Variants
End labels drop deterministically rather than 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. The reclaimed room goes back to the lines. A category name gets as many characters as the width affords, up to 14; under four it drops and hands its gutter back, so a wide chart shows a name a narrow one cannot. Each surviving label seats on its own endpoint and moves at most half a glyph pitch to clear the label above it. One that needs more than that drops, which keeps every name readable against the line it belongs to. Endpoints that would collide inside a column are nudged half a unit apart.
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 is no second point to connect to, so nothing is interpolated, and the row is announced as "incomplete".
With a locale, both column labels and the announced values follow that locale's own grouping.
Four homes
West's renewal rate slid from best to worst region after the March price change — down 25%.
| East | +7pt | |
| West | -14pt | |
| South | +3pt | |
| North | -6pt | |
| Mid | +15pt |
Preview uses the public chart API only. When an interactive twin exists, it swaps in with the same props and no entrance motion - code samples stay on the static import. Placement recipes: Composition, Sizing.
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, press Escape, or
press outside the chart. 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.