OrbitStatus
OrbitStatus carries a dependency's latency as orbit radius and its call rate as dash density, in one square glyph.
- encodes
- orbit radius = latency, dash density / speed = rate
- precision
- low
- nodes
- 3
- collection
- Expressive
OrbitStatus encodes two numbers in one glyph. The orbit radius is latency, so a wider orbit is a slower service, and the
orbit's dash density is the call rate, so denser dashes mean more calls. In the interactive entry the satellite orbits
at a speed that mirrors the rate. Both channels are low-precision ambient reads; for exact numbers use a Sparkline for
latency and a Delta or MiniBar for rate.
Each channel reads against a stated reference. The radius spans 0–1000 ms, or 0–2× threshold when you set one, which
lands the alert edge on the halfway orbit. Dash density steps by decade: under 1 call/s, then 1, 10, 100, and 1000 or
more. Pass domain and rateDomain when you know the range you care about, because a service that answers in 40–90 ms
reads better on its own frame than on the second-wide default.
Install
import { OrbitStatus } from "@microcharts/react/orbit-status";<OrbitStatus latency={240} rate={12} latencyDomain={[0, 500]} rateDomain={[0, 20]} title="Payments API"/>Try it
- hover · click · Enter…
A live dependency table. Each orbit's radius is its latency, its dash density is its call rate, and the satellite's speed mirrors that rate — busier services spin faster. Cross 300ms and the satellite doubles and the row flags. Reduced-motion readers read the same dash density without the spin.
import { OrbitStatus } from "@microcharts/react/orbit-status/interactive";<OrbitStatus latency={240} rate={12} latencyDomain={[0, 500]} rateDomain={[0, 20]}/>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. Rate lives in the dashes as well as the spin, which is what lets a paused satellite
still carry both variables. 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.
Read the satellite's speed, not its angular position; the position encodes nothing.
When to use it
Use it for a live dependency health dot in a service table, for latency and rate together in one small mark, or for an
infra status read. For exact latency or a trend over time use Sparkline; for exact rate use Delta or MiniBar.
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
Edge cases
An unknown latency or rate renders gray, drops the satellite, and stops the spin, so an unreachable dependency never
looks healthy. A rate of 0 draws a solid, dash-free orbit. At threshold the satellite doubles in size. The rate is
quantized to five ordinal steps in both renderings (five dash counts and five angular periods), and radius and speed
read from the same domains in the static and interactive frames.
Four homes
Payments API health — 240 ms latency, 12 req/s, orbit stable.
| payments | 240ms | |
| auth | 48ms | |
| search | 420ms |
Preview uses the public chart API only. When an interactive twin exists, it swaps in with the same props and no entrance motion - code samples stay on the static import. Placement recipes: Composition, Sizing.
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 satellite's size and the summary
carry the threshold state, 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.
Hover or focus also reveals the reading itself in a floating chip, for the sizes and label modes where the mark
does not print it; readout={false} drops the chip and keeps everything else.
Props
| Prop | Type | Notes |
|---|---|---|
| latency* | number | Orbit radius, on the latency reference below. |
| rate* | number | Dash density / satellite speed. |
| domain | [number, number] | Latency extent (default [0, 2·threshold], else [0, 1000] ms). |
| latencyDomain | [number, number] | The same extent under its older name. |
| rateDomain | [number, number] | Rate extent (default: one dash step per decade). |
| threshold | number | Latency threshold: at/above it the satellite doubles + the summary flags it. |
| size | number | Orbit box edge in viewBox units (default 20). |
| fontSize | number | Type size of the gutter label, in viewBox units. Defaults from `size`. |
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.