Skip to content
microcharts
ReferenceDecisionCyclePlot

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.

CyclePlot
interactive · 5.84 kB · static · 3.03 kB

Install

Import & usereact/cycle-plot
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"];
Needs package + stylesheetSet up with AI

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). period outside 4–12 warns in development: below that there is no cycle to see, above it the slots stop being separable.

Sizing

Variants

median center + spine only

Edge cases

one slot always missing
single cycle
locale

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

PropTypeNotes
data*number[]A flat series, reshaped row-major into `period` slots.
period*numberSlots per cycle (4–12) — e.g. 7 for weekdays.
slotsstring[]Slot names for summaries, e.g. weekday labels.
center"mean" | "median"Center statistic — median for skewed slot distributions.
trendbooleanWithin-slot micro-trend line (default true); false = spine + ticks only.
spinebooleanThe slot-center spine (default true); false leaves within-slot drift only.
cycleUnitstringCycle noun for the summary, e.g. 'weeks' (default 'cycles').
animatebooleaninteractiveOpt-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