Skip to content
microcharts
ReferenceExpressiveOrbitStatus

OrbitStatus

React orbit status chart — cyclic status as position on an orbit — where we are in the cycle. Tiny accessible SVG microchart; RSC-safe static or /interactive.

OrbitStatus answers "how slow and how busy is this dependency right now?" in one small mark. The orbit radius is latency — a wider orbit is a slower service — and the orbit's dash density is the call rate, denser dashes meaning more calls. In the interactive entry the satellite orbits at a speed that mirrors that rate, so a busy service visibly spins faster. Both channels are deliberately low-precision ambient reads; for exact numbers, use a Sparkline for latency and a Delta or MiniBar for rate.

OrbitStatus
interactive · 4.14 kB · static · 2.26 kB

Install

Import & usereact/orbit-status
import { OrbitStatus } from "@microcharts/react/orbit-status";<OrbitStatus  latency={240}  rate={12}  latencyDomain={[0, 500]}  rateDomain={[0, 20]}  title="Payments API"/>
Needs package + stylesheetSet up with AI

Try it

Motion, and reduced motion

The satellite's angular speed is quantized to the same five steps as the static dash density, so the motion and the still frame decode identically — you learn nothing extra from watching, you just feel the rate. This is the deliberate idle-loop exception, allowed because the loop rate is the datum. It pauses off-screen and, under prefers-reduced-motion, does not spin at all: the dash density already carries the rate. The satellite's angular position never means anything — only its speed does — so the docs say plainly not to read the angle.

When to use it

  • Good for — a live dependency health dot in a service table, latency and rate together in one small mark, or an infra status glance.
  • Avoid for — exact latency (Sparkline), exact rate (Delta, MiniBar), or a trend over time (Sparkline).

Sizing

One size prop, in viewBox units, sets the orbit box — it defaults to 20. There is no separate width/height: the glyph is square, and the rendered box widens only by the gutter a label reserves. fontSize follows size unless you set it.

Variants

an SLO threshold, and an idle service
locale — the ms gutter numeral and the summary both follow it

Edge cases

unknown latency — gray, no satellite, no spin
idle service — zero rate draws a solid, dash-free orbit

Four homes

Why this default

The dash-density static encoding exists because a paused satellite says nothing — the still frame had to carry both variables or the chart would fail the survivor test, so rate lives in the dashes as well as the spin. The rate is quantized to five ordinal steps in both renderings — five dash counts and five angular periods — and radius and speed always come from the same domains in the static and interactive frames, so nothing drifts. A lone orbit radius is meaningless, so the docs insist on explicit latencyDomain and rateDomain — the same steer as FatDigits. At threshold, the satellite doubles and flags the summary, never relying on color alone. Unknown latency or rate goes gray and stops the spin: an unknown dependency must not look healthy.

Accessibility

The accessible name is both variables with units — "240ms latency at 12 calls/s." — plus "— above threshold" when the latency crosses threshold, or "Latency unknown." when a value is missing. The threshold state is carried by the satellite's size and the summary, never color alone; motion is gated on prefers-reduced-motion; and the live region announces threshold crossings only.

This chart is a single unit, so there is nothing to rove between: a click, tap, Enter or Space selects it and fires onSelect, and no selection stays pinned. That is the scalar half of the shared interaction contract.

Props

PropTypeNotes
latency*numberOrbit radius (weak — pass a domain).
rate*numberDash density / satellite speed.
latencyDomain[number, number]Latency extent (insist on it — a lone radius is meaningless).
rateDomain[number, number]Rate extent (default [0, 2·rate]).
thresholdnumberLatency threshold: at/above it the satellite doubles + the summary flags it.

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