Skip to content
microcharts
ReferenceFrontierHypnogram

Hypnogram

Hypnogram draws which discrete state held over time as flat runs joined by right-angle steps.

encodes
row position (y = state, x = time), no interpolation
precision
high
nodes
≤ 3 paths

Hypnogram draws which state a system was in over time: each state is a flat run at its own height, left to right, joined by right-angle steps. There are no diagonals: a state holds until the next one, so a sloped line would invent readings that never happened. Run lengths and the number of steps carry how choppy the period was. The states order sets the vertical axis, and order is meaningful. Pass it explicitly for ordinal states like sleep depth or incident severity; for nominal states with no rank, mode="lanes" keeps the axis from implying one.

Hypnogram
interactive · 5.51 kB · static · 2.94 kB

Install

Import & usereact/hypnogram
import { Hypnogram } from "@microcharts/react/hypnogram";// sleep — real values under “Sample data” below<Hypnogram data={sleep} states={["Awake","REM","Light","Deep"]} title="Sleep stages" />
Sample data
const sleep = [  { t: 0, state: "Awake" },  { t: 8, state: "Light" },  { t: 22, state: "Deep" },  { t: 38, state: "Light" },  { t: 50, state: "REM" },  { t: 62, state: "Light" },  { t: 74, state: "Deep" },  { t: 86, state: "Light" },  { t: 98, state: "REM" },  { t: 110, state: "Awake" },];
Needs package + stylesheetSet up with AI

Try it

When to use it

Use it for sleep stages and for deploy, machine, or incident state over time. For continuous signals use Sparkline; for a single current state use StatusDot.

Sizing

Variants

lanes (nominal)
emphasis

Edge cases

one state, whole domain
a state outside the explicit order

A single entry holds its state across the whole domain. That is one flat run, and the summary names it directly: "1 state, no transitions; Deep throughout." A state present in the data but missing from an explicit states order is never dropped. It is appended as its own row, with a dev-only console warning, so the strip accounts for every state it is given.

Four homes

Accessibility

The accessible name states the shape: "3 transitions across 4 states; longest run Awake." The interactive entry roves the runs, and each announces its state and span ("Light, from 8 to 22."). Its entrance is a left-to-right clip reveal of the finished trace; smoothing or easing the step corners would change what the data says, so the steps are never interpolated.

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*{ t, state }[]State holds from t to the next entry.
statesstring[]Row order top→bottom; ordinal semantics live here.
emphasisstringAccents one state — the decision read.
mode"steps" | "lanes"Lanes for nominal states with no rank.
connectorsbooleanVertical transition strokes (default true); off for ultra-dense strips.
labelsbooleanLeft-gutter state names (default: on when width ≥ 96).
colorsstring[]Per-state lane colours (lanes mode), cycled; overrides --mc-cat-N.
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