Plot
Canvas time-series — live feeds and fixed-domain analytics, with scrub, series toggle, and loading morph.
Playground
Open Show controls to switch Domain and Live, and to try the axes, legend, inspection and range.
Domain
A fixed historical range. Pass the full domain once; ranges narrow the window from its end and sit in the card's top bar.
Live
A sliding window anchored to now. Append points as they arrive; windows set the span, and paused freezes the scroll without dropping data.
Multi-series
Each series needs an id, label and color. Legend buttons hide a series and rescale the Y axis; at least one stays visible.
Bucket inspection
inspection="bucket" treats each bucketWidth as a window: the scrub snaps to exact observations and highlights that segment of the line. Use it when each value is a whole period, like calls per day.
Guide lines
overlays registers reference lines such as a cap or target; visibleOverlays turns them on. currentPriceLineSeriesIds adds a dashed line at a series' latest value.
Loading
loading draws a breathing line in place of the data, at the card's full height.
Empty
When the range has no points, emptyText replaces the line with a hint to change the range or filters.
Error
error shows your message; pass onRetry to add a Try again action.
Best practices
When to use
- Use PlotCard for a titled time series on analytics pages: call volume, concurrency, latency.
- Use SpotlightChart when several KPIs share one time range and tabs swap the series. Use Stat Strip when the KPIs need no chart.
- Use raw Plot from @smallest-inc/plot only when you need engine features without card chrome, such as candlesticks (chartType="candle", lineMode) or a custom header.
Behavior
- mode defaults to domain: a fixed { start, end } with optional ranges tabs that narrow the window from its end. Use mode="live" for a sliding window anchored to now, with windows and defaultWindow.
- The parent owns mode. The card never renders a Domain/Live switch.
- Put data on series ({ id, label, color, data }) for domain. For live, keep series as metadata and stream points through live.data or live.series with matching ids.
- Scrub is continuous by default. Use inspection="bucket" (plus bucketWidth when the gap cannot be inferred) to snap to exact observations. A missing bucket stays empty.
- axes is both by default: x draws time labels and y draws the value grid. Use axes="none" for sparkline-size cards.
- Guide lines are off by default. Register them with overlays, turn them on with visibleOverlays, and add dashed current-value lines with currentPriceLineSeriesIds.
- Multi-series cards have no fill by default. Use areaFill="lower" so fills never add up visually; use overlap only when every series is a subset of the one above it.
- Legend buttons hide series and rescale Y. At least one series always stays visible.
- loading, emptyText and error (with onRetry) replace the plot while keeping the card's height. paused freezes a live feed without dropping points.
Content
- Title the card with the metric ("Call volume"), not the chart type. Series labels are nouns in sentence case ("Answered").
- Pass formatValue and formatLegendValue that match the product KPI copy, for example rounded counts and "690 ms". formatValue receives the series id.
- Give each series a distinct hex color. Canvas colors cannot read CSS variables.
- Credit Liveline (MIT) from packages/plot/NOTICE when shipping.
Accessibility
- Pass accessibleLabel when title is not plain text. Focusing the plot lets people inspect points with Left/Right and Home/End; Escape clears.
- Legend buttons expose aria-pressed. Do not rely on color alone for multi-series; keep labels in the legend.
- Put a summary or table beside the chart for anything people must read exactly.