import { ScatterChart } from "@elabs-ai/components-charts";npm install @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-chartsPaste it into Claude Code, Cursor, Codex or any other coding agent. Text in [brackets] is yours to fill in.
Add the brand-ui ScatterChart chart (from @elabs-ai/components-charts) to this project. 1. Read https://elabs-ai.com/llms.txt first: it maps every package and the rules. If you can use MCP servers, connect https://elabs-ai.com/mcp and use its search, docs and tokens tools. If not, run the same lookups in the terminal: `npx -y @elabs-ai/components-cli search "<what you need>"` and `npx -y @elabs-ai/components-cli docs <Component>`. 2. Look ScatterChart up before writing code: `npx -y @elabs-ai/components-cli docs ScatterChart` prints its real props, variants, what it pairs with and what to avoid. 3. If @elabs-ai/components-charts is not installed yet: `pnpm add @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-charts` (or `npm install @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-charts`). If this is the first brand-ui package in the project, wire it once: import `@elabs-ai/components-tokens/styles.css` plus the `themes/light.css` and `themes/dark.css` stylesheets in the CSS entry, add one Tailwind `@source` line per installed @elabs-ai package (Tailwind does not scan node_modules, so without it everything renders unstyled), and wrap the app root in `ThemeProvider` from `@elabs-ai/components-tokens`. 4. Use it here: [the screen or file, and what it should show] 5. Rules: use only @elabs-ai/components-* components and the semantic tokens — no raw colours, no raw font sizes, no arbitrary Tailwind values. Look up each component's real props with the docs tool before you use it; never guess a prop. 6. Done means: the typecheck passes, `npx -y @elabs-ai/components-cli audit src --strict` reports nothing, and you have opened the app and looked at every screen you touched in the light and the dark theme.
Use it for
- How is it spread? Two measures per record.
- two continuous measures per row — correlation, or the shape of a distribution
Avoid
- one axis is categorical — use a bar or dumbbell chart
- Connecting the points — a line asserts a sequence a scatter does not have.
- Plotting tens of thousands of raw points — past ~20k use DensityScatterChart (every point drawn, density as colour); below that, bin or sample.
- Distinguishing groups by colour only at default opacity — overlapping marks collapse; add shape or facets.
Works with
Contains
Used inside
Examples
Default
Loading
`status="loading"` (RM-182): a skeleton in the plot box the chart will fill, with one polite status message per chart, at 380, 600 and 900 px.
Legend, hover only
Single Series
With Y Gradient
With Accessible Label
Accessible variant — announces label + description to screen readers on focus.
Plumb
RM-031 — lieflat F8 "Plumb Scatter": every dot hangs a hairline "plumb line" to the floor so its x position can be read straight off the axis. Unit: sessions per day. `dropLines="x"` renders these under the markers and out of hit-testing.
Extremes
Jitter Strip
Numeric X
Selection states
`selectionStates` paints the host’s tri-state on points (keyed on the datum’s region): selected marks carry a compound foreground/background outline, excluded marks dim AND carry a full-opacity dashed frame, so the three states stay distinguishable in greyscale.
Bubble size, colour-by and a log x-axis
Legend, colour key
Bubble Size
A 4x population draws at 2x radius (RM-039 honesty: AREA, not radius, carries the value).
Shape By Column
Each `team` draws with its own marker shape, not just its own colour (WCAG 1.4.1).
With Trend Line
A least-squares fit drawn as dashed furniture; direction/fit reach `data-trend`/`data-r2`. Deprecated: `<Scatter trend>` (used by this story and both trend-summary stories) is an alias of the shared trend analytic and is removed in 7.0.0. Pass `analytics={[{ kind: "trend", of: "revenue", model: "linear" }]}` on `ScatterChart` instead — it also adds the legend entry and the tooltip row.
Trend line with auto summary
With an `accessibleLabel` and no caller `accessibleDescription`, the trend's direction and r² fold into the auto summary — the text behind `aria-describedby`, read by AT, never drawn on screen.
Trend line with a caller-written description
The same trend, but the caller writes its own `accessibleDescription` — the auto summary (and any trend fragment) never overrides a caller's own text.
With Custom Shapes
Custom lines / areas (Datawrapper "custom lines & areas"): a constant `y=`, a constant `x=`, and a multi-point path — all drawn in data space, behind the marks.
Bubble Labels Wide
`sizeKey` doubles as the label priority by default (RM-115 × RM-110): with no explicit `labels.priority`, the biggest bubble's own `population` value decides who keeps a name when the plot cannot fit every one. Wide: most of the 40 names fit.
Bubble Labels Medium
The same 40 bubbles at 600px — fewer names fit than at 900px, more than at 380px.
Bubble Labels Narrow
The same 40 bubbles at 380px: fewer names paint, but every dropped one stays reachable through the `sr-only` restatement beside the plot.
Lived-in: ticket triage (fit, p90 rule, lasso → flagged list)
A support lead's triage view: eighty tickets, the linear fit that says slow answers score lower, the 90th-percentile response time as a computed rule on the x axis, and a lasso (or rectangle) in `explicit` confirm — the set stays provisional until ✓ or Enter, then ONE `replace` intent lands in a local selection driver and the caption lists the flagged ids. The keyboard path is the crosshair rectangle (`S`, arrows, Space).
API
ScatterChart
| Prop | Type | Description |
|---|---|---|
datarequired | Record<string, unknown>[] | Data array — each item should have a date field and numeric values |
xDataKey | string | Key in data for the x-axis (date). Default: "date" |
xScale | ScatterXScaleType | How `xDataKey` values are interpreted (#302). Default: `"time"`, unless every value is already a `number`, which infers `"linear"` — a numeric x (weight, price, …) then renders numeric tick labels and a numeric tooltip title instead of an epoch date. A categorical x remains unsupported (still warns); only `"time"`/`"linear"` are offered. |
margin | number | Partial<Margin> | Chart margins: one number for every side, or per side. Default: 40 on every side. |
animationDuration | number | Animation duration in milliseconds. Default: 1100 |
animationEasing | string | CSS easing for clip-reveal. Default: cubic-bezier(0.85, 0, 0.15, 1) |
enterTransition | Transition | |
revealSignature | string | |
aspectRatio | string | Aspect ratio as "width / height". Default: "2 / 1" |
plotHeight | Responsive<ChartPlotHeight> | The plot's own height (ADR 0039): px, or `{ aspect }` (width ÷ height), optionally per breakpoint. Wins over `aspectRatio`, which stays an alias. |
className | string | Additional class name for the container |
status | ChartStatus | Loading vs ready (RM-182). `"loading"` shows a skeleton in the plot box the chart will fill, with one polite status message, until the data is ready. Default: `"ready"`. |
childrenrequired | ReactNode | Child components (Scatter, Grid, ChartTooltip, XAxis, etc.) |
onPhaseChange | (phase: ChartPhase) => void | |
accessibleLabel | ChartA11yProps["accessibleLabel"] | Accessible name for the chart region (announces to AT on focus). |
accessibleDescription | ChartA11yProps["accessibleDescription"] | Supplemental description read by AT (e.g. series names + value range). |
legend | ContainerLegendProp | Renders a legend beside the plot via `useContainerLegend` (RM-118). Unset renders nothing (R1). `true` uses the default placement/layout; `{ position, layout, values, title }` refines it — `interactive` is capped at `"hover"` (a legend row highlights on hover/focus but never toggles a series' visibility — Scatter has no per-series hide, unlike `BarChart`). One key per chart (RM-118 R4): when any `<Scatter colorBy>` child resolves a non-empty colour key (`resolveColorBy`, `scatter-encodings.ts` — the same categorical/sequential/diverging stops the points themselves draw), the legend lists THAT key instead of the plain per-series (`dataKey`) rows, so only one key ever shows. `shapeBy`'s categories are not represented here — the legend engine has no shape-swatch marker yet (`ChartLegendEntry.marker` doesn't cover it); a `shapeBy`-only chart keeps the plain per-series legend. `{ values: true }` prints a point count per entry: rows with a finite value in the series' `dataKey`, or rows the colour stop paints. |
analytics | readonly ChartAnalytic[] | Statistical overlays computed from `data` (ADR 0040 §1, RM-138 / RM-139): computed `line`/`band`s on EITHER axis (`axis: "x"` reduces the x column), and `trend` (linear, log, exp, pow, polynomial, loess) / `window` / `errorBars` drawn as derived series with a legend entry and a tooltip row. |
annotations | readonly ChartAnnotation[] | Declarative annotations in data units — text notes, ranges and reference lines (RM-111). Always honoured at runtime through the shared annotation layer; RM-188 declares the prop so it is typed and documented. |
tooltip | boolean | Show a hover/focus tooltip. Default `true`: with no `<ChartTooltip>` child the chart adds a default one; a `<ChartTooltip>` child (for `variant`, `rows`, `content`, …) replaces it. `false` turns the default off. |
palette | ChartPalette | Colour ramp for the series (RM-186): each `Scatter` that sets no `fill` / `stroke` of its own takes the next colour of `resolvePalette(palette, n)`. Unset: series cycle the twelve categorical colours, as before. |
selectionStates | ChartSelectionStatesResolver<Record<string, unknown>> | Maps a mark (category, optional series key, optional raw row) to its selection state. Unset → the chart renders exactly as before. |
dimExcluded | boolean | Dim `excluded` marks and add their non-hue channel (the dashed frame). Default `true`; `false` keeps the `data-selection` attribute (so a host can style it) but paints nothing. |
selectionGestures | readonly ChartSelectionGesture[] | Gestures to enable. Unset → no gesture layer, DOM byte-identical to today. |
onSelectionIntent | ChartSelectionIntentHandler<Record<string, unknown>> | Fires with every intent. Required for the gesture layer to mount. |
selectionConfirm | ChartSelectionConfirm | Default `"immediate"`. |
selectionField | string | The field name carried in intents. Default: the chart's `xDataKey`. |
selectionHitRule | ChartSelectionHitRule | Rect / lasso hit rule. Default `"overlap"` (the report-builder BI suite). |
selectionToolbar | "auto" | "none" | `"auto"` (default): a toolbar appears when gestures are enabled; `"none"` hides it. |
Scatter
| Prop | Type | Description |
|---|---|---|
name | string | Series display name: legend and tooltip text. Unset falls back to `dataKey`, same as `Line`/`Area`'s `name`. |
yAxisId | string | number | Y-scale group id (Recharts `yAxisId`). Default: `"left"`. |
animate | boolean | Whether to animate points with clip reveal. Default: true |
yGradient | boolean | { from?: string; to?: string } | Color each dot by its vertical position using a chart-space linear gradient. Lower values use `from`; higher values use `to`. Default stops: red (bottom) → green (top). |
dropLines | "x" | "y" | "both" | false | Draw a hairline "drop line" from each point down to the axis it names — `"x"` to the bottom (x) axis, `"y"` to the left (y) axis, `"both"` for both. Rendered UNDER the markers and excluded from hit-testing (`pointer-events: none`, `aria-hidden`). Default: `false` — no drop lines, today's behavior. |
labelExtremes | { /** Rank by the series' own value (`"y"`) or by x-axis position (`"x"`). */ by: "y" | "x"; /** How many points to label at EACH end (best and worst). Default: 1. */ count?: number; /** Data field to read the point's display label from. */ labelKey?: string; /** Formats the ranked numeric value next to the label. */ format?: (value: number) => string; } | Hero-and-rest labeling (lieflat F8 "Plumb Scatter"): mark the `count` highest AND `count` lowest points (ranked `by`) in full-opacity ink with a `HaloText` label, fading every other point to `fadedOpacity`. `labelKey` names the data field to read the display label from; when omitted the label falls back to the chart's own x-axis date label for that row. `format`, when given, formats the numeric value alongside the label (only applied when the ranked value is a number, i.e. `by: "y"`). |
fadedOpacity | number | Opacity applied to points NOT selected by `labelExtremes`. Default: 0.35. |
jitter | number | Deterministic jitter (`seededRnd` — identical across re-renders and test runs), as a fraction of the row band, `0–0.5`. Requires `yType="category"`; ignored otherwise. |
yType | "number" | "category" | Treat this series' values (`d[dataKey]`) as category labels laid out on a local band scale (one row per distinct value) rather than a numeric y position on the chart's shared y-scale. Default: `"number"` — today's behavior. |
highlightKey | string | ((d: Record<string, unknown>) => boolean) | Highlight matching points with a non-color ring (`PeakRing` — shape, not hue, carries the emphasis; see `.claude/rules/accessibility.md`). A string names a data field read as a truthy flag (`d[highlightKey]`); a function is called with the row and returns whether it is highlighted. |
sizeKey | string | Bubble size by a numeric column (RM-115) — `d[sizeKey]` scales the marker's radius by `sqrt(value / max)` (honesty gate: AREA, not radius, carries the value — see `areaRadius`). Rows missing `sizeKey` (or the whole series, when `sizeKey` is set but every value is non-numeric) draw at `sizeRange[0]`. Unset (default): every marker draws at `radius`. |
sizeRange | [number, number] | `[minRadius, maxRadius]` in px for `sizeKey`. Default: `[4, 22]`. |
colorBy | ScatterColorByConfig | Colour each point by a fixed/categorical/numeric column (RM-115) instead of the series' own colour. A row whose `colorBy.key` is missing/unusable keeps drawing in the series' own `fill`. See `scatter-encodings.ts`' `resolveColorBy` — a consumer building a legend (RM-118) calls it with the same `data`/`colorBy` to get the identical colour stops. |
shapeBy | ScatterShapeByConfig | Shape each point by a categorical column (RM-115), cycling through the series-marker ramp (≤ 6 shapes; a 7th+ distinct value repeats the last shape). See `resolveShapeBy` for the legend a consumer (RM-118) reads. |
trend | "linear" | "log" | false | A least-squares trend line (RM-115): `"linear"` (`y = a + bx`) or `"log"` (`y = a + b·ln(x)`, points with a non-positive x dropped). `false` (default): no trend line. See `trend-line.tsx` for the regression space it fits in and its accuracy caveat for `"log"` on a `xScale="linear"` chart. @deprecated Use `analytics={[{ kind: "trend", of: dataKey, model }]}` on `ScatterChart` — the shared trend analytic, which adds the legend entry, the tooltip row and every trend model. `trend` keeps drawing the same line as an alias of it until its removal in 7.0.0. |
labels | ScatterLabels | Point labels with collision avoidance (RM-110): `{ key, mode?, priority? }` — `key` is the row field holding the label text; `mode` `"auto"` (default: thinned by plot area, fewer at narrow widths) | `"all"` | a predicate; `priority` decides who survives (default: the y value). Wave-1 integration (RM-115 × RM-110): when `sizeKey` is set and `labels` does not supply its own `priority`, the bubble's OWN `sizeKey` value becomes the priority reader — the biggest bubbles keep their labels first, matching what the eye already reads as "important" on a bubble chart. Every label that is not painted is restated `sr-only` by the chart. Unlike `labelExtremes` it never fades the unlabelled points. |
dataKeyrequired | string | |
fill | string | Marker fill color. Defaults to series stroke or chart palette color. |
placement | "all" | "ends" | "first" | "last" | Which points get a marker (RM-112, `Line`/`Area` `symbols`). `"all"` (today's behaviour, and the default when unset) renders one per point; `"ends"` only the first and last defined point; `"first"`/`"last"` only that one. |
pointSlot | string | `data-slot` for every point's `<g>` (opt-in, #549) — `Scatter` passes `"scatter-point"` so its animated path names points like its static one. |
stroke | string | Outer ring stroke color. Default: same as `fill` |
strokeWidth | number | Outer ring stroke width in px. Default: 2. Set to 0 to disable. |
ringGap | number | Gap between the inner fill and outer ring in px. Default: 2 |
outlineWidth | number | Optional outer outline beyond the ring. Default: 0 |
outlineColor | string | Outer outline color. Default: same as `stroke` |
radius | number | Point radius in px. Default: 5 |
fadeOnHover | boolean | Dim non-active points while hovering. Default: true |
inactiveOpacity | number | Opacity for non-hovered points when `fadeOnHover` is true. Default: 0.5 |
inactiveBlur | number | Blur in px for non-hovered points when `fadeOnHover` is true. Applied once on the dimmed layer (not per dot) for performance. Default: 2 |
enterBlur | number | Initial blur in px during enter animation. Default: 2 |
showActiveHighlight | boolean | Enlarge the active point while hovering. Default: true |
shape | SeriesMarkerShape | Marker shape. Default: "circle". Used for series differentiation under high decoration. Does not affect the ring — only the filled inner shape. |
XAxis
| Prop | Type | Description |
|---|---|---|
numTicks | number | @deprecated Use `tickCount` — `numTicks` still wins when both are set, exactly as before (ADR 0042 A.2, row 6). Read until 7.0.0, with one development warning. |
tickCount | AxisTickCount | Tick target (RM-108). `"auto"` (default) derives it from the plot width — `tickTargetForWidth(innerWidth)`, about one tick per 90 px, clamped 2–10, and never more than the number of data rows on a time axis (6 monthly rows get at most 6 ticks, not 9 labels between them). |
ticks | Date[] | number[] | RM-108 naming, shared with `YAxis`. On a time axis: an alias of `tickValues` (`tickValues` wins). On a numeric x with `domain`/`scale` (ScatterChart): exactly these raw x values. |
domain | AxisDomain | Numeric x only (ScatterChart with numeric `xDataKey`, RM-108): pin either end of the x domain in raw units; `"auto"` keeps the data-derived end. Read by the chart container, so place `XAxis` as a direct child. Setting `domain` or `scale` also switches the labels from one per data row to a numeric ruler. Ignored on a time axis. |
scale | ValueScaleType | Numeric x only (RM-108): `"linear"` (default), `"log"` (refuses data or a domain touching 0 — dev warning, renders linear) or `"sqrt"`. |
position | XAxisOrientation | Which edge the labels sit on (RM-108). Default: `"bottom"`. |
orientation | XAxisOrientation | @deprecated Use `position` — the same values (ADR 0042 A.2, row 10). Read until 7.0.0, with one development warning; when both are set, `position` wins. |
title | ReactNode | Axis title (RM-108). |
titlePlacement | AxisTitlePlacement | `"outside"` (default) — in the margin beyond the tick labels, at the far end; `"inside"` — `HaloText` at the far end inside the plot. |
tickerHalfWidth | number | Width of the date ticker box for fade calculation. Default: 50 |
tickMode | "domain" | "data" | `"domain"` — evenly spaced ticks across the time domain (default). `"data"` — one label per data row at its x value (better with sparse or monthly bars). |
tickFormat | (value: Date) => string | Override the default `Intl`-based tick label formatter. Applied to every tick this axis renders (generated or `tickValues`). #357. **Time scale only.** Ignored (with a dev warning) when the chart runs `xScale="band" | "linear"` — those modes project onto a synthetic instant, so a `Date` formatter would print a fabricated calendar date instead of your x value. Format categorical/numeric x values in your data. #352. |
dateFormat | DateFormatPreset | ((value: Date) => string) | The date-format LADDER (RM-109): a preset from `date-format.ts` (`"year"` → `"yearShort"` → `"month"` → `"day"` → `"weekday"` → `"hour"` → `"minute"`), or a formatter function for full control. Unset (default) — the axis picks a rung itself via `dateFormatForSpan`, from the time domain's span and how many ticks are on screen, instead of the old fixed `"Mon d"` shape whatever the span. A ten-year series reads years; a 36-hour series reads hours. `tickFormat` still wins outright when both are set — it is the raw escape hatch this package has always had; `dateFormat` is the smart default underneath it. Same time-scale-only caveat as `tickFormat` (#352). |
tickValues | Date[] | Render exactly these tick positions, bypassing tick generation AND the default label-collision de-dupe entirely — use when the default de-dupe would collapse the axis (e.g. dense data whose formatted labels collide). #357. **Time scale only** — see `tickFormat`. #352. |
periodTicks | XAxisPeriodTicks | false | Draw a `HairlineFloor` (RM-017) below the plot — one hairline tick per calendar period, whether or not a data row falls on it, with the long tick anchored to a real calendar boundary (day → the first day of the week, week → the first week of the month, month → January), not an index stride from wherever the series happens to start (#253). Lieflat provenance: the ruled foot of a ledger page gives a reader the passage of time with no labels and no axis. This is a SEPARATE visual layer from the labelled ticks above (`numTicks` / `tickMode`) — it never changes which labels render or where. `false` (default) draws nothing — today's behaviour. |
YAxis
| Prop | Type | Description |
|---|---|---|
yAxisId | string | number | Scale group id (Recharts `yAxisId`). Default: `"left"`. |
position | YAxisOrientation | Which side of the chart to render labels. Default: `"left"`. |
orientation | YAxisOrientation | @deprecated Use `position` — the same values (ADR 0042 A.2, row 11). Read until 7.0.0, with one development warning; when both are set, `position` wins. |
numTicks | number | @deprecated Use `tickCount` — `numTicks` still wins when both are set, exactly as before (ADR 0042 A.2, row 7). Clamped to {@link Y_AXIS_MIN_TICK_COUNT}–{@link Y_AXIS_MAX_TICK_COUNT}. Read until 7.0.0, with one development warning. |
tickCount | AxisTickCount | Tick target (RM-108). `"auto"` (default) derives it from the plot height — `tickTargetForHeight(innerHeight)`: 3 under 200 px, else 5. |
ticks | number[] | Render exactly these tick values (RM-108), bypassing generation. |
domain | AxisDomain | Pin either end of the value domain (RM-108); `"auto"` keeps the data-derived end. Read by the chart container, so place `YAxis` as a direct child. On a length encoding (bars) the domain always includes 0 — a non-zero lower bound is ignored with a dev warning (`charts-honesty`). |
scale | ValueScaleType | How values map to pixels (RM-108). `"log"` refuses data or a domain that touches 0 (dev warning, renders linear); bars are linear only. Default: `"linear"`. |
title | ReactNode | Axis title — names the unit of every tick (RM-108). |
titlePlacement | AxisTitlePlacement | `"outside"` (default) — above the top tick label in the margin; `"inside"` — `HaloText` at the top of the axis inside the plot. |
labelPlacement | AxisLabelPlacement | `"outside"` (default) — tick labels in the margin beside the plot; `"inside"` — labels sit just above their grid line inside the plot. |
valueFormat | ChartValueFormat | How tick values are rendered. Default: `"compact"` — `1.5M`, not `1500k` and not `1500000`. Pass `"number"` for every digit. |
currency | string | ISO 4217 code for `valueFormat: "currency"`. Falls back to `ChartConfigProvider`, then `"USD"`. |
formatValue | (value: number) => string | Custom formatter for tick labels. Overrides `valueFormat` entirely when set. |
unit | string | Unit text appended to {@link unitOn} tick(s) — `<YAxis unit="%" />` paints `"80 %"` on that tick, not every tick (RM-109). The tooltip is the place a unit repeats on every value (the blog's "3.4 % unemployed", not a bare "3.4 %"); see `TooltipRow.unit`. |
unitOn | "last" | "first" | "all" | Which tick(s) {@link unit} paints on. Default: `"last"`. |
matchSeriesColor | boolean | Paint the tick labels and title in the colour of this axis' series when it carries exactly ONE series; neutral otherwise (RM-121, Datawrapper's "label colour: match data"). The text goes through `seriesLabelInk` — the stroke mixed toward the label ink so it still reads at 4.5:1. Default `false`. |
sideLabel | ReactNode | "auto" | A caption naming which scale this is, above the tick column (RM-121). `"auto"` → "Left scale" / "Right scale" by `position`, through the locale seam (`charts.axis.leftScale` / `charts.axis.rightScale`). |
Grid
| Prop | Type | Description |
|---|---|---|
mode | GridMode | Grid painting mode (RM-108). Default: `"lines"`. |
horizontal | boolean | Show horizontal grid lines. Default: true |
vertical | boolean | Show vertical grid lines. Default: false |
numTicksRows | number | Number of horizontal grid lines. Default: the height-derived target shared with `YAxis` (`tickTargetForHeight(innerHeight)` — 3 under 200 px, else 5), so rows and labels stay aligned (RM-108). |
numTicksColumns | number | Number of vertical grid lines. Default: 10 |
rowTickValues | number[] | Explicit tick values for horizontal grid lines. Overrides numTicksRows. |
stroke | string | Grid line stroke color. Default: var(--chart-grid) |
loadingStroke | string | Grid stroke while loading chrome is active. Falls back to `stroke`. |
strokeOpacity | number | Grid line stroke opacity. Default: 1 |
strokeWidth | number | Grid line stroke width. Default: `CHART_HAIRLINE_WIDTH` — the one furniture weight. |
strokeDasharray | string | Grid line dash array. Default: "4,4" for dashed lines |
highlightRowValues | number[] | Horizontal row values rendered with alternate styling (e.g. zero baseline). |
highlightRowStroke | string | Stroke for highlighted rows. Default: var(--chart-foreground-muted) |
highlightRowStrokeOpacity | number | Stroke opacity for highlighted rows. Default: 1 |
highlightRowStrokeWidth | number | Stroke width for highlighted rows. Default: 1 |
highlightRowStrokeDasharray | string | Dash array for highlighted rows. Default: solid line |
highlightRowLabel | (value: number) => string | undefined | Text label drawn at the right edge of each `highlightRowValues` entry (`HaloText`, so it survives sitting on the grid) — a KPI target/goal line the reader can name, not just see. Return `undefined`/`""` to skip the label for a given value. Unset (default): no label, byte-identical to before this prop existed. |
highlightColumnValues | Array<number | Date> | Vertical reference lines at these `xDataKey`-domain values (e.g. "today" on a forecast chart) — the column counterpart of `highlightRowValues`. Default: none. |
highlightColumnStroke | string | Stroke for highlighted columns. Default: var(--chart-foreground-muted) |
highlightColumnStrokeOpacity | number | Stroke opacity for highlighted columns. Default: 1 |
highlightColumnStrokeWidth | number | Stroke width for highlighted columns. Default: 1 |
highlightColumnStrokeDasharray | string | Dash array for highlighted columns. Default: solid line |
highlightColumnLabel | (value: number | Date) => string | undefined | Text label drawn at the bottom-inside, left of each `highlightColumnValues` entry (`HaloText`), e.g. "Today". Return `undefined`/`""` to skip the label for a given value. Unset (default): no label. |
fadeHorizontal | boolean | Enable horizontal fade effect on grid rows (fades at left/right). Default: true |
fadeVertical | boolean | Enable vertical fade effect on grid columns (fades at top/bottom). Default: false |
yAxisId | string | number | Y-scale for horizontal grid lines. Default: primary (`"left"`) axis. |
shimmer | boolean | Animate a shimmer band across horizontal grid lines. Default: false |
shimmerStroke | string | Shimmer band stroke (color and opacity via color-mix or oklch alpha). |
shimmerLength | number | Shimmer band width in pixels. Default: 140 |
shimmerSpeed | number | Shimmer speed multiplier (higher = faster). Default: 1 |
shimmerSync | boolean | Match loop timing to the loading line pulse (cycle + inter-loop pause). |