Heartwood Health · How to Build

05 · Slope Chart.

← components.html
all how-tos
05
Slope Chart

Two-period comparison · paired data points

Underused. A slope chart says everything a 2-bar grouped bar says, with half the ink and a clearer rank-change signal.

When to use

Comparing the same metric across the same set of categories at exactly two points in time. Outcome scores 2024 vs 2025, NPS Q1 vs Q4. Lines that cross are a feature, not a bug — they show category rank-flips, which a side-by-side grouped bar makes invisible.

How it animates

Each <line> draws left → right via the same stroke-dasharray trick as the line chart. Dots fade in when the line arrives at each end. Labels follow the dots. Stagger 100ms per series so the eye can track each line individually.

Data shape
outcomeScores: {
  leftYear:  2024,    // editable
  rightYear: 2025,
  series: [
    { label: 'Cardiology',
      left: 78, right: 86,
      color: 'var(--primary)' },
    // any number of series
  ],
}
Build pattern
const all   = series.flatMap(s => [s.left, s.right]);
const minV  = Math.min(...all) - 5; // pad bottom
const maxV  = Math.max(...all) + 2; // pad top
const scale = (v) =>
  padTop + (1 - (v - minV) / (maxV - minV)) * usableH;
⚠ Watch

Pad your Y-axis range. If the scale is set to exactly [min(values), max(values)], your lowest point sits on the baseline and reads as zero. The script pads min − 5 on the bottom and max + 2 on top — adjust if your value range demands different breathing room.