Component

CometChart

Temporal scatter chart for how entities move through a two-metric space over time. Use it when the story is direction of change, not just a current snapshot. Hero fixture: approximate Premier League team-season npxG/npxGA values derived from public FBref-style summaries for 2022-23 and 2023-24.

0.811.21.41.61.822.2npxG per 900.60.811.21.41.61.8npxGA per 90
Man City
Arsenal
Liverpool
Newcastle
Man Utd
Chelsea
Tottenham
Brighton
Aston Villa
Brentford
Fulham
Crystal Palace
Wolves
West Ham
Bournemouth
Nottm Forest
Everton
Leicester
Leeds
Southampton
Stories

Canonical behaviors.

Team Logos

Logo markers can replace circles without changing the chart model.

1.21.41.61.822.2npxG per 900.70.80.911.11.21.3npxGA per 90
Arsenal
Newcastle
Aston Villa
Single-Entity Evolution

One entity over many seasons. Useful when the story is a single team or player arc.

2.533.544.55Passes per sequence1.51.61.71.81.92Direct speed upfield (m/s)
Inverted Y-Axis

Useful when lower values are better and should appear higher on the chart.

1.21.41.61.822.2npxG per 900.70.80.911.11.21.3npxGA per 90 (lower = better)
Arsenal
Newcastle
Aston Villa
Dense Field

All teams visible with default labeling. This is the main overlap stress case.

0.811.21.41.61.822.2npxG per 900.60.811.21.41.61.8npxGA per 90
Man City
Arsenal
Liverpool
Newcastle
Man Utd
Chelsea
Tottenham
Brighton
Aston Villa
Brentford
Fulham
Crystal Palace
Wolves
West Ham
Bournemouth
Nottm Forest
Everton
Leicester
Leeds
Southampton
Barely Moved

When change is negligible, entities collapse down to dots rather than exaggerated trails.

11.21.41.61.822.2npxG per 900.70.80.911.11.21.3npxGA per 90
Arsenal
Aston Villa
Fulham
Crystal Palace
Empty State

No points, no fake trail geometry.

00.20.40.60.81npxG per 9000.20.40.60.81npxGA per 90
No data
Long And Multilingual Labels

Stress case for mixed-script labels and long end annotations near the latest point.

1.31.41.51.61.71.8npxG per 900.90.9511.051.11.151.2npxGA per 90
Borussia Mönchengladbach
横浜F・マリノス
Athletic Club de Bilbao
Dark Theme

ThemeProvider can restyle the chart without changing the grouped point model.

1.21.41.61.822.2npxG per 900.70.80.911.11.21.3npxGA per 90
Arsenal
Newcastle
Aston Villa
Recipes

Composition patterns.

Methodology Notes

Use the shared note seam for sample framing instead of rebuilding chart-card copy around the component.

1.21.41.61.822.2npxG per 900.70.80.911.11.21.3npxGA per 90
Arsenal
Newcastle
Aston Villa
Sample: selected clubs across two seasons only. Metric definitions stay upstream; CometChart only visualizes the temporal movement.
Cross-cutting

Shared concerns.

Choose CometChart

Use CometChart when the movement across time is the story. If you only need one snapshot, use a plain scatter chart.

Time Ordering

`timeKey` controls the trail order. Without it, array order becomes part of the visual contract.

Labels And Guides

Selective labels and median guides are usually enough. Over-labeling makes the trail story harder to read.

Accessibility

Markers and trail groups both expose tooltip content on hover. Marker buttons remain keyboard-focusable so the latest point is not the only inspectable state.

Export Posture

CometChart is intentionally outside the current stable `ExportFrameSpec` union. Treat it as a live React chart today rather than an export-safe chart card.

Responsive Behavior

CometChart is most legible in a wide analytical panel. On smaller widths the trail direction must survive before dense labeling or guide copy does.

Composition

The chart already owns trail, marker, and tooltip semantics. Shared methodology notes can stay inside the chart frame; broader narrative annotation should stay outside.

Responsive

Width pressure.

Compact Container

A smaller width keeps the directional read, but should not try to keep every label and guide at full verbosity.

0.811.21.41.61.822.2npxG per 900.60.811.21.41.61.8npxGA per 90
Man City
Arsenal
Liverpool
Newcastle
Man Utd
Chelsea
Tottenham
Brighton
Aston Villa
Brentford
Fulham
Crystal Palace
Wolves
West Ham
Bournemouth
Nottm Forest
Everton
Leicester
Leeds
Southampton
Wide Analytical Panel

Wide layouts preserve more trail separation, guide labels, and collision-free annotations.

0.811.21.41.61.822.2npxG per 900.60.811.21.41.61.8npxGA per 90
Man City
Arsenal
Liverpool
Newcastle
Man Utd
Chelsea
Tottenham
Brighton
Aston Villa
Brentford
Fulham
Crystal Palace
Wolves
West Ham
Bournemouth
Nottm Forest
Everton
Leicester
Leeds
Southampton
Usage

Best-practice examples.

Minimal usage

CometChart needs entity grouping plus two plotted metrics. Time is optional but usually the point of the chart.

                    import { CometChart } from "@withqwerty/campos-react";

export function TeamEvolution({ points }) {
  return (
    <CometChart
      points={points}
      entityKey="team"
      xKey="npxgPer90"
      yKey="npxgaPer90"
      timeKey="season"
      xLabel="npxG per 90"
      yLabel="npxGA per 90"
    />
  );
}
                  
Guide and label variant

Guides and labels are first-class style surfaces, and trail or marker styling can be injected without changing the chart model.

                    import { CometChart } from "@withqwerty/campos-react";

export function TeamEvolutionGuides({ points }) {
  return (
    <CometChart
      points={points}
      entityKey="team"
      xKey="npxgPer90"
      yKey="npxgaPer90"
      timeKey="season"
      xLabel="npxG per 90"
      yLabel="npxGA per 90"
      labelStrategy="manual"
      labelIds={["Arsenal", "Liverpool", "Brighton"]}
      guides={[
        { axis: "x", value: "median", label: "Median npxG" },
        { axis: "y", value: "median", label: "Median npxGA" },
      ]}
      lines={{
        stroke: ({ entity }) => (entity.id === "Arsenal" ? "#dc2626" : "#2563eb"),
        strokeDasharray: ({ entity }) => (entity.barelyMoved ? "3 3" : undefined),
      }}
      labels={{ fill: "#111827", connectorStroke: "#94a3b8" }}
      guideStyle={{ stroke: "#94a3b8", opacity: 0.45 }}
    />
  );
}
                  
API

Public surface.

Prop Type Default Description
points readonly T[] required Array of data objects, each representing one entity at one time point.
entityKey keyof T & string required Field that groups rows into entities.
xKey keyof T & string required Field to plot on the x-axis.
yKey keyof T & string required Field to plot on the y-axis.
timeKey keyof T & string Field used to sort points chronologically within each entity.
xLabel string xKey X-axis label.
yLabel string yKey Y-axis label.
labelKey keyof T & string entityKey Field used for entity labels and tooltip identity.
invertX boolean false Flip x-axis so higher values appear left.
invertY boolean false Flip y-axis so higher values appear lower.
guides readonly CometChartGuideInput[] Vertical or horizontal guide lines using a number, mean, or median.
showTimeLabels boolean false Show time labels at each point.
labelStrategy "all" | "none" | "manual" "all" How entity labels are chosen.
labelIds readonly string[] Subset of entity ids to label when labelStrategy is manual.
lines CometChartLinesStyle First-class line styling surface for trail segments.
markers CometChartMarkersStyle First-class point styling surface for comet markers.
labels CometChartLabelsStyle First-class label styling surface for entity labels.
guideStyle CometChartGuidesStyle First-class styling surface for rendered guide lines and labels.
methodologyNotes ChartMethodologyNotes Shared chart-frame note seam for sample, eligibility, and methodological context.
logoMap Record<string, string> Map entity ids to image URLs so markers render as logos instead of circles. Live React/browser seam only; CometChart is not yet in the stable export union.

`logoMap` is supported in the live React component, but CometChart is still deferred from the stable `ExportFrameSpec` contract. The current export-safe matrix should not imply static/chart-card parity for this component yet.

Use with AI
LLM Prompt
Create a React component using Campos CometChart. Import CometChart from @withqwerty/campos-react, keep data shaping outside the component, show the smallest good usage first, then one variant with median guides and selective labels.