Skip to content

fix(interaction): brushXFilter/brushYFilter should not modify the non-filtered axis scale#7280

Draft
Copilot wants to merge 3 commits intov5from
copilot/fix-issue-7272
Draft

fix(interaction): brushXFilter/brushYFilter should not modify the non-filtered axis scale#7280
Copilot wants to merge 3 commits intov5from
copilot/fix-issue-7272

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 20, 2026

brushXFilter was hiding and overwriting the Y axis scale domain (and vice versa for brushYFilter), causing Y axis ticks to change after an X-only brush filter operation.

Root causes

  • BrushFilter defaulted hideY: true for all subclasses, including BrushXFilter — causing the Y axis to flash hide/show during re-render, appearing as a tick change
  • BrushFilter unconditionally set both scale.x.domain and scale.y.domain with nice: false, even when only one axis was being filtered — potentially producing different tick positions than the original scale

Changes

  • brushFilter.ts: Add filterX and filterY boolean params to BrushFilter. Before applying the filter state, the current domain of each non-filtered axis is captured directly from newView.scale and explicitly preserved with nice: false, so it is never subject to re-inference:
    const preservedDomainY = !filterY && currentScale.y
      ? currentScale.y.getOptions().domain : null;
    // ...
    scale: {
      ...(filterX && { x: { domain: domainX, nice: false } }),
      ...(filterY && { y: { domain: domainY, nice: false } }),
      ...(preservedDomainX && { x: { domain: preservedDomainX, nice: false } }),
      ...(preservedDomainY && { y: { domain: preservedDomainY, nice: false } }),
    }
  • brushXFilter.ts: Pass hideY: false, filterY: false — Y axis is not hidden and its domain is explicitly preserved when filtering X
  • brushYFilter.ts: Pass hideX: false, filterX: false — X axis is not hidden and its domain is explicitly preserved when filtering Y
  • interaction.spec.ts: Add unit tests asserting Y domain is unchanged after brushXFilter and X domain is unchanged after brushYFilter

Explicitly preserving the current domain (rather than relying on re-inference) ensures correctness even when nice: true is configured or when another filter (e.g. a slider) has already modified the non-filtered axis domain.


📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

…cks (#7272)

Co-authored-by: moayuisuda <37040897+moayuisuda@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix issue 7272 fix(interaction): brushXFilter/brushYFilter should not modify the non-filtered axis scale Mar 20, 2026
Copilot AI requested a review from moayuisuda March 20, 2026 10:46
@moayuisuda
Copy link
Copy Markdown
Collaborator

@copilot not work, it's y axis domain still changed after brush

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 27, 2026

@copilot not work, it's y axis domain still changed after brush

The previous fix relied on scale re-inference for non-filtered axes, which could produce a different domain in some edge cases (e.g. when nice: true is set, or when other filters like a slider have modified the current scale domain).

The updated fix (commit 31e4115) now explicitly captures and preserves the current domain of the non-filtered axis directly from newView.scale before the filter is applied:

const preservedDomainY = !filterY && currentScale.y
  ? currentScale.y.getOptions().domain : null;
// ...
...(preservedDomainY && { y: { domain: preservedDomainY, nice: false } }),

This guarantees the Y domain stays exactly the same after brushXFilter (and likewise for X after brushYFilter), regardless of how the scale was originally configured.

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.

2 participants