Skip to content

fix(tooltip): don't run callbacks when the filter removes every item - #12319

Open
Minhal128 wants to merge 1 commit into
chartjs:masterfrom
Minhal128:fix/tooltip-filtered-empty-callbacks
Open

Minhal128 wants to merge 1 commit into
chartjs:masterfrom
Minhal128:fix/tooltip-filtered-empty-callbacks

Conversation

@Minhal128

Copy link
Copy Markdown

Fixes #12274

The problem

Tooltip#update() decided whether the tooltip had anything to show by looking at this._active:

if (!active.length) {
  // hide
} else {
  tooltipItems = this._createItems(options);
  this.title = this.getTitle(tooltipItems, options);
  ...
}

options.filter is applied inside _createItems, after that branch is chosen. So when a filter rejects every active element there are still active elements, the visible branch runs, and getTitle / getBody / getFooter are invoked with an empty TooltipItem[].

That breaks callbacks which reasonably assume at least one item — as reported, users have to add a guard to their title callback that is unnecessary in every other situation.

The change

Build the items first, then branch on the filtered result. A tooltip with nothing left to show is now treated the same as one with no active elements: callbacks are skipped and it stays hidden.

_createItems is still called exactly once per update, and is still skipped entirely when there are no active elements, so dataPoints / labelColors keep their existing lifecycle.

Verification

Added a regression test that filters out every item and asserts the title callback is never invoked and the tooltip stays at opacity: 0.

I ran the full CI suite on a fork before opening this (workflow_dispatch on the branch), and the same suite on unmodified master as a baseline:

tests result
master (baseline) 1703 1 failed — controller.polarArea/pointLabels/overlapping.js, Firefox
this branch 1704 same 1 failure, nothing else

That single failure is a pre-existing pixel fixture on Firefox and is present without this change. Windows is fully green on both.

When `options.filter` rejected every active element, `update()` still took
the visible branch because it only checked `active.length`. The title,
body and footer callbacks were then invoked with an empty TooltipItem
array, which broke callbacks that reasonably assume at least one item.

Build the items first and branch on the filtered result instead, so a
tooltip with nothing left to show is treated like one with no active
elements: the callbacks are skipped and the tooltip stays hidden.
Copilot AI lite review requested due to automatic review settings September 24, 2026 14:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tooltip title callback is run with empty parameter array for filtered tooltips

2 participants