Skip to content

[docs][charts] Add synchronized tooltip and crosshair demo - #23368

Merged
JCQuintas merged 10 commits into
mui:masterfrom
JCQuintas:docs/charts-synchronized-tooltip-demo
Aug 27, 2026
Merged

JCQuintas merged 10 commits into
mui:masterfrom
JCQuintas:docs/charts-synchronized-tooltip-demo

Conversation

@JCQuintas

@JCQuintas JCQuintas commented Aug 18, 2026 •

Copy link
Copy Markdown
Member

Adds a docs demo showing how to synchronize the tooltip and crosshair across several charts that share an x axis.

Closes #17555.

Approach

The demo uses only public API:

  • One lifted AxisItemIdentifier[] state passed to every chart as highlightedAxis and updated by every chart's onHighlightedAxisChange, so hovering any chart highlights the same index on all of them. axisHighlight={{ x: 'line' }} then draws the crosshair everywhere.
  • The built-in tooltips are turned off with slotProps={{ tooltip: { trigger: 'none' } }}.
  • A single tooltip is rendered outside the charts with Popper and a virtual anchor that follows the pointer, reading data[dataIndex] for each chart. This follows the same pattern as the existing ItemTooltipFixedY demo.

useAxesTooltip and useItemTooltip are not usable here: they read the interaction state of the chart they are mounted in, so they only ever return that chart's series.

Notes for follow up

Two rough edges surfaced while building this. Neither blocks the demo, but both are worth tracking separately:

  • There is no public way to follow the pointer across sibling charts. ChartsTooltipContainer binds pointermove to its own layer container, so the virtual anchor has to be reimplemented in userland.
  • There is no public way to align drawing areas across charts. The demo hardcodes yAxis.width so the crosshairs line up. With width: 'auto' the axis widths differ per chart and the crosshairs drift apart.

The demo is pointer driven. Keyboard navigation still moves highlightedAxis, but the tooltip anchor stays at the last pointer position.

Demonstrates sharing `highlightedAxis` between stacked line charts and
rendering a single tooltip that reads every chart at the shared dataIndex.
@JCQuintas JCQuintas added type: enhancement It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature. docs Improvements or additions to the documentation. scope: charts Changes related to the charts. labels Aug 18, 2026
@JCQuintas JCQuintas self-assigned this Aug 18, 2026
@code-infra-dashboard

code-infra-dashboard Bot commented Aug 18, 2026 •

Copy link
Copy Markdown

Deploy preview

Bundle size

Bundle Parsed size Gzip size
@mui/x-data-grid 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-pro 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-premium 0B(0.00%) 0B(0.00%)
@mui/x-charts 0B(0.00%) 0B(0.00%)
@mui/x-charts-pro 0B(0.00%) 0B(0.00%)
@mui/x-charts-premium 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers-pro 0B(0.00%) 0B(0.00%)
@mui/x-tree-view 0B(0.00%) 0B(0.00%)
@mui/x-tree-view-pro 0B(0.00%) 0B(0.00%)
@mui/x-scheduler 0B(0.00%) 0B(0.00%)
@mui/x-scheduler-premium 0B(0.00%) 0B(0.00%)
@mui/x-chat 0B(0.00%) 0B(0.00%)
@mui/x-license 0B(0.00%) 0B(0.00%)

Details of bundle changes


Check out the code infra dashboard for more information about this PR.

@JCQuintas
JCQuintas requested a review from noraleonte August 18, 2026 10:45
@alexfauquette

Copy link
Copy Markdown
Member

Look nice. Just need to increase the y-axis space to avoid the elipses

image

@JCQuintas

Copy link
Copy Markdown
Member Author

Look nice. Just need to increase the y-axis space to avoid the elipses

thats actually a different issue 🤔

Seems ellipsis are being added because of the label crosses the top margin, if we increase the top margin on the demo it fixes it 😮

The string measurement cache is shared by every chart on the page and was never
invalidated, so a size measured with the fallback font, before the web font
finished loading, stayed cached for the lifetime of the page.

`batchMeasureStrings` also left its styles on the shared measurement container,
so a later call omitting one of those properties measured with the previous
call's value. And the cache was wiped entirely once it passed 2000 entries,
which made a measurement depend on how many strings were measured before it.

Reset the container style between calls, evict the oldest entries instead of
wiping the whole cache, and clear the cache when fonts finish loading.
`getStringSize` caches sizes in a module level map and every regression test
shares a single page, so a demo could reuse a size measured by an earlier one,
including sizes measured before the fonts finished loading. Axis label
truncation then depended on the order the tests ran in and on how many strings
were measured before, which showed up as screenshot diffs in unrelated demos.

Export `clearStringMeasurementCache` from the charts internals and call it in
`TestViewer` whenever the route changes. It runs during render because the
children measure their text before any effect fires.
@JCQuintas
JCQuintas enabled auto-merge (squash) August 27, 2026 10:20
@JCQuintas
JCQuintas disabled auto-merge August 27, 2026 10:21
@JCQuintas
JCQuintas merged commit 70090ee into mui:master Aug 27, 2026
22 checks passed
@JCQuintas
JCQuintas deleted the docs/charts-synchronized-tooltip-demo branch August 27, 2026 10:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to the documentation. scope: charts Changes related to the charts. type: enhancement It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[charts] Synchronized tooltips and crosshair

2 participants