CyclePlot
CyclePlot reshapes a series into seasonal slots, connecting the slot means and drawing each slot's drift.
- encodes
- slot-mean spine + within-slot micro-trend
- precision
- medium
- nodes
- 2 per slot + 2 (cap 12)
Friday peaks at 61, Sunday dips to 38, and slot 2 has been climbing across three cycles. CyclePlot reshapes the series
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 is the spine and
drift is the within-slot lines: two questions of the same data, on two marks.
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
Use it for a KPI card that says "the week has a shape", for weekday traffic / hourly load / monthly sales seasonality,
or for spotting one slot that is itself drifting. For a plain time series reach for Sparkline; for one composition,
SegmentedBar. A period outside 4–12 warns in development: below that there is no cycle to see, above it the slots stop
being separable.
Sizing
Variants
center picks the slot statistic: mean by default, "median" when a slot's distribution is skewed. The interactive
per-slot announcement names which one it used. trend={false} drops the spine and leaves the within-slot lines. Those
lines are never smoothed and never joined across a slot boundary — each polyline begins and ends inside its own column,
so a Monday trend cannot bleed into Tuesday.
Edge cases
A slot with no finite values 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, since a line needs at least two observations in a slot.
Four homes
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.