Xzero UI
Pro library

Connected scatterPro

A connected scatterplot of monthly CAC against LTV where the path draws itself in, a scrubber moves a head along the curve, and a channel switch morphs the path against a shaded 3x target line.

$ pnpm dlx shadcn@4.23.0 add @xzero-ui-pro/connected-scatter
Live · keyboard ready

Render <ConnectedScatter /> for the demo, or pass series (same number of points in each, in time order), xAxis, yAxis, targetRatio and formatValue for your own two metrics. Listen to onMonthChange to sync the month the head settles on.

When to use

When not to use

Installation

Register both Xzero UI namespaces in your project's components.json:

{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
npx shadcn@4.23.0 add @xzero-ui-pro/connected-scatter

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

Usage

import { ConnectedScatter } from "@/components/xzero/blocks/connected-scatter/connected-scatter";

export function UnitEconomics() {
  return (
    <ConnectedScatter
      defaultSeries="partners"
      onMonthChange={index => setSelectedMonth(index)}
    />
  );
}

API reference

ConnectedScatter

A connected scatterplot of two metrics over time. Each month is a point, joined in time order by a smooth path with small direction arrows. The path draws itself in once, a head marks the selected month and a time scrubber moves it along the path, a channel switch morphs the path point by point to another series, and a dashed target line (LTV = 3x CAC) splits the plot with the healthy side lightly shaded. Hovering a point shows its date and both values.

PropTypeDefaultDescription
seriesScatterSeries[]SERIESSeries to switch between: id, name, points in time order ({ label, x, y }) and optional notes ({ index, text, side }) that label key months. Every series needs the same number of points so the path can morph.
defaultSeriesstring–Id of the series shown first. Defaults to the first series.
xAxisScatterAxisX_AXISHorizontal axis: short name for the readout, title printed on the axis, min, max and gridline step. The sample is CAC from $200 to $1,800.
yAxisScatterAxisY_AXISVertical axis, same shape. The sample is 12 month LTV from $2,000 to $6,000.
targetRationumber3Slope of the reference line y = targetRatio times x. The region above it is shaded as healthy and the readout says whether the selected month is above or below it.
formatValue(value: number) => stringwhole US dollarsFormats values in the readout, the tooltip, the axis ticks and the screen reader table.
titlestring"CAC and LTV by channel"Block heading.
descriptionstring–One line under the heading. Defaults to a sentence naming the metrics and the date range.
onMonthChange(index: number) => void–Called with the month index whenever the head settles on a month: a released scrub, a key press, a tap on a point, or the end of playback. Not called on every frame.
classNamestring–Class on the root element.

Keyboard interactions

KeysAction
TabMoves through the channel switch, the play button and the month scrubber.
Arrow left / Arrow rightOn the scrubber, moves the head one month back or forward along the path.
Page up / Page downOn the scrubber, moves three months at a time.
Home / EndOn the scrubber, jumps to the first or last month.
Arrow keys in the channel switchSwitch channel; the path morphs to the new series.
Enter / Space on the play buttonPlays through the months from the head, pauses, or replays from the first month at the end.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Guidance for AI tools

Blocks are complete, self-contained screens with sample data. Replace the sample data and connect the callbacks described above. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt

Browse all components