PolarClock
PolarClock draws a 24-hour or 7-day cycle as radial bars at fixed angles, growing from an inner baseline.
- encodes
- radial bar length at a fixed cycle angle
- precision
- medium
- nodes
- 4
PolarClock turns each value in a cycle into a radial bar at its fixed angle, growing outward from an inner baseline and zero-anchored there. Longer bars are busier times. Midnight (or your week start) sits at 12 o'clock and the cycle runs clockwise. The channel is length, not sector area: equal-value bars at the rim cover more area than ones near the hub, which is why the inner radius is nonzero. Compare lengths, not wedges.
Install
import { PolarClock } from "@microcharts/react/polar-clock";// byHour — real values under “Sample data” below<PolarClock data={byHour} now={14} title="Traffic by hour" />Sample data
// 24 hourly values, midnight → 23:00const byHour = [ 80, 81, 82, 83, 20, 85, 86, 87, 88, 89, 90, 91, 92, 93, 312, 95, 96, 97, 98, 99, 100, 101, 102, 103,];Try it
When to use it
Use it for the shape of a 24-hour or 7-day cycle, for when a metric is busy across that cycle, and for a compact
seasonal read in a KPI card. For exact value comparison unroll the cycle into a SparkBar; for a non-cyclic trend use
Sparkline. Keep it under a few dozen segments.
Sizing
Variants
At very small sizes, where length is hard to judge, mode="opacity" switches the channel to a five-step fill — a radial
ActivityGrid. That is a named change of encoding, not a cosmetic one.
The four cardinal ticks default on because a bare ring of bars is rotationally ambiguous: without a mark for 12 o'clock
there is no way to tell where the cycle starts. They are merged into one path, so the orientation cue costs a single
node. Set labels={false} only when the shape itself is the whole story and the axis genuinely doesn't matter.
Edge cases
A null segment leaves a gap and the baseline ring shows the hole, because missing is not the same as zero. A cycle
where every value is equal draws every bar at the same length.
Four homes
Accessibility
The accessible name states the peak and the quiet point of the cycle — "Peaks at 14:00 (1.240); quietest 04:00." —
with hour labels for a 24-segment cycle and weekday names for a 7-segment one. The interactive entry lets you arrow
through the segments circularly, each announced with its label and value through a polite live region, and the accented
now segment carries position and color, never color alone.
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 | null)[] | One value per cycle division (24 hourly, 7 daily, any n). |
| now | number | Index of the current segment to accent. |
| inner | number | Inner radius fraction r0 — the zero baseline bars grow from (default 0.35). |
| mode | "length" | "opacity" | Radial bars (default) or fixed-length 5-step fill. |
| origin | number | Index rendered at 12 o'clock (week-start / midnight). |
| labels | boolean | Hairline cardinal ticks at 0/¼/½/¾ — the at-rest orientation cue. Default true. |
| segmentFormat | (index, n) => string | Segment index → label (default: HH:00 for n=24, weekday for n=7, else index). |
| size | number | Dial box edge in viewBox units (default 24). |
| fontSize | number | Type size of the peak label under the dial, in viewBox units. Defaults from `size`. |
| 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.