import { ChartTooltip } 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 ChartTooltip 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 ChartTooltip up before writing code: `npx -y @elabs-ai/components-cli docs ChartTooltip` 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.
Avoid
- Putting information ONLY in the tooltip — hover content is unreachable by keyboard and on touch.
- Showing every series in a shared tooltip on a dense chart — filter to the hovered series.
- Formatting numbers by hand — use Intl so locale and units stay consistent with the axis.
Works with
Used inside
Pairs with
Examples
Table
`variant="table"` — one column per series, header row, date in the `<caption>`.
Inline
`variant="inline"` — no box, the hovered series' value painted at the mark (the bikes chart).
Focus
`focus` — the tooltip's nearest-series resolution drives RM-112's per-series dim (`SeriesHoverDim`): hovering closer to one series' line fades the other two to the shared excluded opacity. `ChartTooltip focus` registers the request on its own — no `focusOnHover` on the `LineChart` container below.
Touch Pin
`pin` — on a coarse pointer, a tap keeps the tooltip open after the finger lifts; a second tap, `Esc`, or a tap outside the chart releases it. `pin={true}` forces the affordance in this story regardless of the test runner's pointer type.
Small Chart
A 140×56 chart — the Small Multiples panel. There is no room beside the pointer inside it, so the box steps OUTSIDE the chart, beside it, and stays there while the pointer scrubs; it never covers the chart or the cursor. The date pill has no gutter to sit in, so it does not show.
Clear Of Pointer
#605's shape: the wide `table` box in a 380px chart. Wherever the pointer goes, the box sits beside it — never on it, never over the hovered dots.
Keyboard Clear
Keyboard: stepping through the points with the arrow keys, the box keeps clear of the focused target and its focus ring.
API
ChartTooltip
| Prop | Type | Description |
|---|---|---|
showDatePill | boolean | Whether to show the date pill under the plot. Default: shown when it fits the chart's bottom margin (≥ 36px) — never painted over a small plot. |
showCrosshair | boolean | Whether to show the vertical crosshair line. Default: true |
showDots | boolean | Whether to show dots on the lines. Default: true |
indicatorColor | string | ((point: Record<string, unknown>) => string) | Color for the crosshair/indicator line. When a function, receives the hovered point (e.g. for candlestick: match candle color from close vs open). Default: --chart-crosshair. |
content | (props: { point: Record<string, unknown>; index: number }) => React.ReactNode | Custom content renderer for the tooltip box |
rows | (point: Record<string, unknown>) => TooltipRow[] | Custom row renderer - return array of TooltipRow |
variant | ChartTooltipVariant | Box layout preset (RM-119). `"rows"` (default) is today's stacked `ChartTooltipContent`. `"table"` renders `ChartTooltipTable` — one column per series with a header row, the date in the `<caption>` (Datawrapper's dual-axis / multi-series shape, `dw-charts.md` §2.22). `"inline"` renders no box at all — `ChartTooltipInline` paints the hovered (or `focus`-nearest) series' value directly at the mark with `HaloText` (the bikes chart). Ignored when `content` is set — a custom renderer already owns the whole box. |
focus | boolean | Drive RM-112's per-series dim (`SeriesHoverDim`) from the tooltip's OWN nearest-series resolution: whichever series' y position is closest to the pointer, at ANY x along the crosshair, counts as hovered — not only a direct hover on that series' own 2px stroke. Works standalone: it registers "focus requested" on the shared series-mode context, so the dim fires with no `focusOnHover` prop on the `LineChart`/`AreaChart` container (a container `focusOnHover` still works exactly as before, and the two compose — either one turns the dim on). Also the default target series for `variant="inline"`. Default false. |
pin | boolean | Tap-to-pin (RM-119): on a coarse pointer, a tap keeps the tooltip open instead of clearing the instant the finger lifts. A second tap on the mark, `Esc`, or a tap outside the chart releases it (announced once via `role="status" aria-live="polite"`). Default: `true` only when the pointer is coarse (`(pointer: coarse)` media query); pass an explicit boolean to force either way regardless of pointer type. |
valueInTitle | boolean | Swap the tooltip box's own title for nothing — the hovered value moves to the chart's OWN title instead (RM-119, #610). Inside a `ChartFrame` that shows a title this is automatic: while a row is hovered, pinned or keyboard-focused the frame's title reads "Apr: Revenue 40" and is announced once through the frame's polite status; leaving restores the title. No wiring. Outside a frame (or in `chrome="bare"`, a custom `headerSlot`, the expanded dialog) only the box title is dropped — the date/category is still on `useChart().tooltipData` for a custom title. Default false. |
dotColor | string | ((point: Record<string, unknown>, line: LineConfig) => string) | Override tooltip dot fill. When omitted and `rows` is set, dot colors match row colors. When a function, receives the hovered point and line config. |
children | React.ReactNode | Additional content to show below rows (e.g., markers) |
className | string | Custom class name |
springConfig | SpringConfig | Per-chart override for the crosshair / dot / date-pill spring. |
boxSpringConfig | SpringConfig | Per-chart override for the floating-panel spring. |
panelStyle | React.CSSProperties | Inline styles for the tooltip panel (background, blur, etc.). |
unit | string | Unit text appended to every DEFAULT row's value (RM-109) — the same `unit` `<YAxis>` paints on one tick. Set automatically from the chart's own `<YAxis unit>` when unset (the shell threads it through); pass it explicitly only to override. Ignored when `rows` is set — a custom row builder owns its own `TooltipRow.unit` per row. |
valueFormat | ChartValueFormat | STYLE to borrow from the chart's own `<YAxis valueFormat>` for DEFAULT rows (RM-109) — a currency symbol, a percent sign — never abbreviation (`ChartTooltipContent`'s doc). Set automatically from `<YAxis valueFormat>` when unset; ignored when `rows` is set. |
currency | string | ISO 4217 code for `valueFormat`'s `style: "currency"`. |
ChartTooltipBox
| Prop | Type | Description |
|---|---|---|
xrequired | number | Anchor X in pixels, relative to the container — a crosshair, a mark centre. |
yrequired | number | Anchor Y in pixels, relative to the container. |
visiblerequired | boolean | Whether the tooltip is visible |
containerRefrequired | RefObject<HTMLDivElement | null> | The chart container: the box is portaled into it and placed around it. |
containerWidthrequired | number | Container width in the chart's own pixels (scales `x`/`avoid` to the screen). |
containerHeightrequired | number | Container height in the chart's own pixels. |
offset | number | Space kept between the box and the pointer or marks it avoids. Default 16. |
className | string | Custom class name |
childrenrequired | React.ReactNode | Tooltip content |
left | number | ReturnType<typeof useSpring> | @deprecated Bypasses placement: the box is positioned inside the container at this left, as before placement existed, and can cover the pointer. |
top | number | ReturnType<typeof useSpring> | @deprecated Bypasses placement: the box is positioned inside the container at this top, as before placement existed, and can cover the pointer. |
flipped | boolean | @deprecated Only read with `left`/`top`: the side the entrance slides from. |
springConfig | SpringConfig | Per-chart override; falls back to `ChartConfigProvider.tooltipBoxSpring`. |
panelStyle | React.CSSProperties | Inline styles for the inner tooltip panel. |
avoid | ChartTooltipAvoid | readonly ChartTooltipAvoid[] | The hovered mark(s) the box must not cover — a dot, a bar's band, a cell, a node. Small marks are stepped around; a mark too large to avoid (a big treemap leaf) is covered by at most half. The pointer and a keyboard-focused target are always avoided without being listed here. |
track | ChartTooltipTrack | How the anchor moves: `"x"` for a crosshair scrubbing along x (the box keeps its top at `y`), `"y"` for rows, `"free"` (default) for a mark anywhere in the plot. |
pinned | boolean | Freezes the placement while a touch tooltip is pinned (the finger has lifted). |
ChartTooltipContent
| Prop | Type | Description |
|---|---|---|
title | string | |
rowsrequired | TooltipRow[] | |
children | ReactNode | Optional additional content (e.g., markers) |
valueFormat | ChartValueFormat | STYLE to borrow from the chart's own `valueFormat` (RM-109) — a currency symbol, a percent sign, an explicit sign, a prefix/suffix. `abbreviate` is always forced `false` regardless of what this spec asks for: the tooltip is the detail-on-demand surface (see the module doc below), so it never compacts. Default: plain grouped digits (`"number"`), byte- identical to every call site from before this prop existed. |
currency | string | ISO 4217 code for `valueFormat`'s `style: "currency"`. |
ChartTooltipDot
| Prop | Type | Description |
|---|---|---|
xrequired | number | |
yrequired | number | |
visiblerequired | boolean | |
colorrequired | string | |
size | number | |
strokeColor | string | |
strokeWidth | number | |
springConfig | SpringConfig | Per-chart override; falls back to `ChartConfigProvider.tooltipSpring`. |
ChartTooltipIndicator
| Prop | Type | Description |
|---|---|---|
xrequired | number | X position in pixels (center of the indicator) |
heightrequired | number | Height of the indicator |
visiblerequired | boolean | Whether the indicator is visible |
width | IndicatorWidth | Width of the indicator - number (pixels) or preset. Ignored if `span` is provided. |
span | number | Number of columns/days to span, with current point centered. Requires `columnWidth` to be set. |
columnWidth | number | Width of a single column/day in pixels. Required when using `span`. |
colorEdge | string | Primary color at edges (10% and 90%) |
colorMid | string | Secondary color at center (50%) |
fadeEdges | boolean | Whether to fade to transparent at 0% and 100% |
animate | boolean | Animate position with a spring. Default: true |
gradientId | string | Unique ID for the gradient |
springConfig | SpringConfig | Per-chart override; falls back to `ChartConfigProvider.tooltipSpring`. |
ChartTooltipInline
| Prop | Type | Description |
|---|---|---|
xrequired | number | Hovered point x, plot-area coordinates (no margin offset — the caller's `<g>` already translates). |
yrequired | number | Hovered point y, plot-area coordinates. |
textrequired | string | Already-formatted value text (RM-109 formatting happens in the caller, same as every other variant). |
colorrequired | string | The hovered series' own ink — matches its line/area stroke. |
pointerY | number | null | The pointer's y, same plot coordinates. When it sits where the label would go (just above the point) the label moves below the point instead, so it never hides under the cursor. |
ChartTooltipTable
| Prop | Type | Description |
|---|---|---|
title | string | The hovered date/category — painted as the `<caption>`, never a header cell. |
rowsrequired | TooltipRow[] | One column per series (`ChartTooltip`'s already-resolved `rows`). |
valueFormat | ChartValueFormat | Same STYLE-only borrow as `ChartTooltipContent` — never abbreviated. |
currency | string | ISO 4217 code for `valueFormat`'s `style: "currency"`. |