React Streaming Chart

The live plot every telemetry dashboard needs: a window that scrolls, a bounded buffer, and a pause that freezes the display without pretending the stream stopped. New samples enter at the right edge; the buffer is adjustable while it runs.

Spindle temperature — live

streaming · 120/120 samples · 250ms

75.58°C

69.8475.3380.81critwarn
min 70.90 · avg 75.94 · max 79.75

Installation

npx shadcn@latest add "https://kelvinui.com/registry/streaming-chart.json"

Props

PropTypeDescription
sample(tick: number) => numberPure function of the tick index
intervalMsnumberMilliseconds between samples (default 250)
defaultBuffernumberInitial window size (default 120)
maxBuffernumberSlider maximum (default 300)
min maxnumberFixed y-range; auto-scales to the window if omitted
warningAt criticalAtnumberOptional limit lines
unit titleLabels

Why sample must be pure

This is the one component where a static export and a live animation genuinely fight each other. The buffer is prefilled on first render so the chart is never empty — and that prefill runs on the server too. If sample used Math.random(), the server and client would produce different buffers and React would throw a hydration mismatch on every load.

So sample takes a tick index and must return the same value for the same index, forever. The demo builds its noise from Math.sin(tick * 12.9898) — a standard deterministic hash — rather than a PRNG with hidden state. Streaming itself only starts after mount, inside an effect, which never runs on the server.

In production you usually have real data rather than a generator: keep the same shape by pushing incoming samples into a ref and having sample read from it, or lift the buffer into your own state and pass it down. The buffer slice (slice(length - buffer)) caps memory regardless of how long the page stays open — an unbounded array is how these components eventually take a tab down.

New components every week

Get the week's new Kelvin UI components and templates in one short email. No spam, unsubscribe anytime.