KQ-1654 · GHOST/BASELINE

Ghost Baseline

A metric explorer with a chart, a legend table and window controls, whose comparison is a ghost: turning on Yesterday or Last week lays the same window from earlier under the live lines, sliding in from the left on springs.glide while a clip sweeps across the plot on an enter tween, and the legend's comparison and delta columns roll to their figures. The axis is chosen from the live and the comparison data together, so the ghost never rescales the chart, and a failed refresh keeps the last result drawn. The plot is a slider over its buckets — Left and Right step the crosshair, Shift steps ten, Home and End jump — and [ and ] shift the window anywhere in the explorer.

KQ-1654 · GHOST/BASELINE

Request latency

Wed 14 16:00 – Thu 15 16:00

p95(http.request.duration) by route · service:waylight-api

NowNo comparison

p95, msLatest · 15:55

Request latency at Thu 15:55
RouteNowThenΔ
/v1/orders181––
/v1/search252––
/v1/auth101––

Turn on a comparison to lay an earlier window under these lines.

24h · no comparison

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/ghost-baseline

Props

ghostStyle
"dashed" | "dotted" | "area"
default "dashed"
How the comparison is drawn: dashes, dots, or a soft area under a thin edge.
lineWidth
number
default 1.5
Stroke width of the live lines in px; the ghost is drawn at 80% of it.
palette
"cobalt" | "mono" | "warm" | "cool"
default "cobalt"
The series colours, from the theme's tokens.
query
string
default defaultMetricQuery
The query behind the chart, shown in mono under the title.
series
MetricSeries[]
default defaultMetricSeries
The series: { id, label, points: { t, v | null }[] } with evenly spaced readings; null is a gap.
comparisons
MetricComparison[]
default defaultMetricComparisons
The comparisons on offer: { id, label, short, offset } where offset is how far back it looks in ms.
compare / defaultCompare
string | null
default — / null
The comparison id, controlled or initial; null for none.
onCompareChange
(id: string | null) => void
default —
Fires from the press that changed the comparison.
range / defaultRange
MetricRange
default — / { span: "24h", end: now }
The window, controlled or initial: { span: "1h" | "6h" | "24h" | "7d", end } in ms.
onRangeChange
(range: MetricRange) => void
default —
Fires from the press or key that moved or resized the window.
spans
MetricSpan[]
default ["1h", "6h", "24h", "7d"]
The window sizes on offer.
now
number
default defaultMetricNow
The newest moment there can be data for, in ms; the window never moves past it. Never read from the clock.
unit
string
default "ms"
The readings' unit.
status
"ready" | "loading" | "error"
default "ready"
Whether the result has arrived. Loading keeps the axes; error keeps the last result drawn under a Retry banner.
onRetry
() => void
default —
Retry was pressed after a refresh failed.
maxPoints
number
default 160
The most points drawn per series; the window is averaged into this many buckets.
title
string
default "Request latency"
The chart's name and the explorer's accessible name.
height
number
default 540
Height of the explorer in px; its body scrolls inside it.
className
string
default —
Classes for the outer surface.