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