CyclePlot
React cycle plot chart — seasonal slots with within-slot drift on a shared spine. Tiny accessible SVG microchart; RSC-safe static or /interactive.
CyclePlot answers "what repeats beneath the trend — and is any slot itself drifting?". The series is reshaped into
period slots (7 for weekdays, 12 for months); each slot shows its own raw values across cycles as a muted polyline in
time order, plus a mean tick, and the accent spine connects the slot means. Seasonality (the spine) and drift (the
within-slot lines) are different questions of the same data — so they never share a mark.
Install
import { CyclePlot } from "@microcharts/react/cycle-plot";// daily, weekdays — real values under “Sample data” below<CyclePlot data={daily} period={7} slots={weekdays} cycleUnit="weeks" title="Weekly shape" />Sample data
// 6 weeks of daily traffic — the week has a shape; Mondays are drifting upconst daily: number[] = [];for (let w = 0; w < 6; w++) daily.push(38, 40 + w * 2, 45, 48, 52, 61, 44);const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];Try it
When to use it
- Good for — a KPI card that says "the week has a shape", weekday traffic / hourly load / monthly sales seasonality, or spotting one slot that is itself drifting.
- Avoid for — a plain time series (Sparkline) or one composition (SegmentedBar).
periodoutside 4–12 warns in development: below that there is no cycle to see, above it the slots stop being separable.
Sizing
Variants
Edge cases
A slot with no finite values in it draws no mean tick and no within-slot line; the spine connects the non-empty slots only, joining an empty slot's neighbours directly rather than dipping to a made-up center. A single cycle (one value per slot) draws the spine and dots as usual, but no within-slot polylines — a line needs at least two observations in a slot.
Four homes
Why this default
A mean spine plus raw slot lines, because seasonality and drift are different questions asked of the same data — and
answering both on one mark would blur them. The within-slot lines are never smoothed and never joined across a slot
boundary: each slot's polyline begins and ends inside its own column, so a Monday trend can never bleed into Tuesday.
The center choice is explicit — mean by default, median when a slot's distribution is skewed — and the interactive
per-slot announcement names which one it used.
Accessibility
The accessible name states the peak and dip slots and any leading drift — "Peaks slot 6 (61), dips slot 1 (38); slot 2 rising across 3 cycles." The interactive entry steps the slots (mean, cycle count, drift) with ←/→, and steps the individual observations within a slot with ↑/↓.
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* | number[] | A flat series, reshaped row-major into `period` slots. |
| period* | number | Slots per cycle (4–12) — e.g. 7 for weekdays. |
| slots | string[] | Slot names for summaries, e.g. weekday labels. |
| center | "mean" | "median" | Center statistic — median for skewed slot distributions. |
| trend | boolean | Within-slot micro-trend line (default true); false = spine + ticks only. |
| spine | boolean | The slot-center spine (default true); false leaves within-slot drift only. |
| cycleUnit | string | Cycle noun for the summary, e.g. 'weeks' (default 'cycles'). |
| 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
QuadrantDot
React quadrant dot chart — a focal 2-D point against peers on a split cross. Tiny accessible SVG microchart; RSC-safe static or /interactive.
ChangePoint
React change-point chart — regime breaks marked on a series with mean hairlines. Tiny accessible SVG microchart; RSC-safe static or /interactive.