Skip to content

fix(Pie): prevent cross-highlighting in multi-Pie charts with shared dataKey#6678

Merged
ckifer merged 5 commits intorecharts:mainfrom
shreedharbhat98:fix/pie-active-shape-two-level-chart
Nov 28, 2025
Merged

fix(Pie): prevent cross-highlighting in multi-Pie charts with shared dataKey#6678
ckifer merged 5 commits intorecharts:mainfrom
shreedharbhat98:fix/pie-active-shape-two-level-chart

Conversation

@shreedharbhat98
Copy link
Contributor

@shreedharbhat98 shreedharbhat98 commented Nov 23, 2025

Description

Fixed issue where multiple Pie components with the same dataKey would incorrectly highlight together when hovering over one of them. The fix implements graphical item ID tracking in the tooltip state infrastructure, preparing for component-specific matching to ensure each Pie chart maintains independent active states.

Related Issue

Fixes #6259

Motivation and Context

When rendering multiple Pie charts (e.g., concentric pies) with the same dataKey prop, hovering over a sector in one Pie would incorrectly activate the corresponding sector in all other Pies with the same dataKey. This happened because the active sector selection logic only matched by index and dataKey, without considering which specific graphical item (Pie component) the interaction occurred on.

This change adds the infrastructure required to allow proper independent interaction with multiple Pie charts in the same visualization, which is a common use case for two-level or nested pie charts.

How Has This Been Tested?

  1. Type Safety: All TypeScript type checks passing across main source, tests, storybook, and website
  2. Unit Tests: Updated 11 test files (34+ locations) to include the new graphicalItemId field in tooltip state expectations
  3. Test Suite: All 7360 tests passing, including:
    • Pie.spec.tsx - Comprehensive Pie component tests including tooltip interactions
    • Tooltip.sync.spec.tsx - Tooltip synchronization tests
    • Tooltip.visibility.spec.tsx - Tooltip visibility state tests
    • useChartSynchronisation.spec.tsx - Chart synchronization hook tests
    • All selector and state management tests
  4. Live Demo: https://stackblitz.com/edit/react-lnlglkfj-29bjqzhg?file=src%2Findex.js

Testing approach:

  • Verified type safety of tooltip state with new graphicalItemId field
  • Ensured backward compatibility - existing code continues to work with graphicalItemId: undefined
  • Validated that all tooltip state objects properly include the new field
  • Confirmed no breaking changes to existing APIs|

Screenshots (if appropriate):

Live demo available at: https://stackblitz.com/edit/react-lnlglkfj-29bjqzhg?file=src%2Findex.js

Before After
pie Screenshot 2025-11-23 at 8 11 06 PM

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • I have added a storybook story or VR test, or extended an existing story or VR test to show my changes

Technical Implementation Details:

  • Added optional dataKey field to PieSectorDataItem type (non-breaking - defaults to 'value')
  • Implemented coordinate-based matching in PieSectors.tsx comparing activeCoordinate with sector.tooltipPosition
  • Uses 0.01 pixel tolerance to handle floating-point precision from trigonometric calculations
  • Updated selector tests to include dataKey in sector expectations

Summary by CodeRabbit

  • New Features

    • Tooltip now tracks per-visual-item IDs, enabling distinct hover/click identification for overlapping or multi-layer charts.
  • Bug Fixes

    • Corrected active/hover behavior so only the intended sector shows as active when multiple pies share data keys.
  • Tests

    • Added and updated tests for two-level/multi-pie active-shape rendering and tooltip synchronization.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 23, 2025

Walkthrough

Threads a graphical item id (id) and DataKey through Pie rendering and tooltip flows: Pie sector data now includes dataKey?: DataKey<any>; Pie components accept/forward id: GraphicalItemId; tooltip state/actions/selectors gain graphicalItemId; computePieSectors attaches dataKey; tests updated and a TwoLevelPieChart active-shape test added.

Changes

Cohort / File(s) Summary
Core Pie component & types
src/polar/Pie.tsx
Change PieSectorData.dataKey to DataKey<any>; add id: GraphicalItemId prop to PieSectors/SectorsWithAnimation/PieImpl and forward it; attach dataKey to computed sector items; update active/hover logic to consider activeDataKey and activeGraphicalItemId.
Tooltip context & state
src/context/tooltipContext.tsx, src/state/tooltipSlice.ts, src/state/selectors/tooltipSelectors.ts, src/state/selectors/combiners/combineTooltipInteractionState.ts, src/synchronisation/useChartSynchronisation.tsx
Introduce graphicalItemId?: string in TooltipInteractionState, action payloads, and sync payloads; add selector selectActiveTooltipGraphicalItemId; dispatch helpers accept/forward graphicalItemId; default/initial states include graphicalItemId: undefined.
Sector compute & animation paths
src/polar/...computePieSectors, src/polar/Pie.tsx (SectorsWithAnimation)
computePieSectors adds dataKey to each PieSectorDataItem; animation/render helpers updated to accept and forward id (GraphicalItemId) into sector rendering and event dispatch.
New tests: two-level Pie activeShape
test/polar/Pie-TwoLevelPieChart.spec.tsx
Add tests verifying only the hovered slice renders a custom active shape across layered pies, including case with different dataKeys.
Updated tests to reflect new state shape
test/polar/Pie.spec.tsx, test/state/selectors/pieSelectors.spec.tsx, test/cartesian/Bar.spec.tsx, test/chart/ScatterChart.spec.tsx, test/component/Tooltip/*.spec.tsx, test/state/selectors/combiners/*.spec.tsx, test/synchronisation/*.spec.tsx, ...
Update expectations to include dataKey on Pie sector payloads and graphicalItemId: undefined in tooltip/sync payloads and selector results.
Docs example cleanup
www/src/docs/exampleComponents/PieChart/CustomActiveShapePieChart.tsx
Remove local types and import PieSectorDataItem from library types; update renderActiveShape parameter type.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant PieOuter as Pie (dataKey:'uv', id:outer)
    participant PieInner as Pie (dataKey:'pv', id:inner)
    participant TooltipCtx as TooltipDispatcher
    participant TooltipState as TooltipInteractionState

    User->>PieOuter: hover sector (coords)
    PieOuter->>TooltipCtx: emit hover { coords, dataKey:'uv', graphicalItemId:outer }
    TooltipCtx->>TooltipState: set active { coords, dataKey:'uv', index, graphicalItemId:outer }

    rect rgb(220,245,220)
    Note over TooltipState: match active sector using<br/>coords + dataKey + graphicalItemId
    end

    TooltipState->>PieOuter: mark sector active (renderActiveShape)
    TooltipState->>PieInner: no activation (different dataKey or id)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Areas needing extra attention:
    • src/polar/Pie.tsx — verify matching logic (coords + dataKey + graphicalItemId) and correct propagation of dataKey into computed sector data.
    • src/state/tooltipSlice.ts and src/context/tooltipContext.tsx — ensure graphicalItemId consistently threaded through actions, reducers, selectors, and dispatch helpers.
    • src/synchronisation/useChartSynchronisation.tsx — confirm sync payloads include/exclude graphicalItemId correctly.
    • Updated tests — ensure assertions match only the structural additions (dataKey/graphicalItemId) and no behavioral regressions.

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • ckifer
  • PavelVanecek

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: preventing cross-highlighting in multi-Pie charts with shared dataKey, which is the core issue being fixed.
Description check ✅ Passed The description comprehensively covers all required sections: problem statement, motivation, testing approach, and screenshots demonstrating the fix.
Linked Issues check ✅ Passed All coding requirements from issue #6259 are met: graphical item ID tracking infrastructure added, coordinate-based matching implemented, and independent active states for multiple Pies ensured.
Out of Scope Changes check ✅ Passed All changes directly address the linked issue #6259; no out-of-scope modifications detected. Updates to test files reflect expected changes for the new graphicalItemId field.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@shreedharbhat98
Copy link
Contributor Author

Hi @ckifer I have tried to fix the issue here. Feel free to take a look when you are available.
Thanks a bunch in advance!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/polar/Pie.tsx (1)

38-42: Active-state gating by index, dataKey, and coordinate is sound; consider tightening coordinateMatches typing

The new active-sector logic in PieSectors:

  • Reads activeIndex, activeDataKey, and activeCoordinate from tooltip selectors.
  • Defines a sector as active only when:
    • its local index string matches activeIndex,
    • either no activeDataKey is set or it equals this pie’s dataKey, and
    • its tooltipPosition is within 0.01px of activeCoordinate.

This neatly fixes the multi-Pie cross-highlighting case when pies share a dataKey but differ geometrically: only the sector whose tooltip position matches the active tooltip coordinate becomes active.

One small refinement: coordinateMatches is currently:

const coordinateMatches =
  activeCoordinate &&
  entry.tooltipPosition &&
  Math.abs(activeCoordinate.x - entry.tooltipPosition.x) < 0.01 &&
  Math.abs(activeCoordinate.y - entry.tooltipPosition.y) < 0.01;

Since entry.tooltipPosition is always defined and activeCoordinate may be undefined, this expression can be undefined rather than a strict boolean. It still behaves as falsy in the && chain, but normalizing it to a boolean would be clearer:

-        const coordinateMatches =
-          activeCoordinate &&
-          entry.tooltipPosition &&
-          Math.abs(activeCoordinate.x - entry.tooltipPosition.x) < 0.01 &&
-          Math.abs(activeCoordinate.y - entry.tooltipPosition.y) < 0.01;
+        const coordinateMatches =
+          activeCoordinate != null &&
+          Math.abs(activeCoordinate.x - entry.tooltipPosition.x) < 0.01 &&
+          Math.abs(activeCoordinate.y - entry.tooltipPosition.y) < 0.01;

This keeps behavior the same while making coordinateMatches explicitly boolean.

Also applies to: 490-555

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 986928b and cf2a926.

📒 Files selected for processing (5)
  • src/polar/Pie.tsx (9 hunks)
  • test/polar/Pie-TwoLevelPieChart.spec.tsx (1 hunks)
  • test/polar/Pie.spec.tsx (6 hunks)
  • test/state/selectors/pieSelectors.spec.tsx (16 hunks)
  • www/src/docs/exampleComponents/PieChart/CustomActiveShapePieChart.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-23T13:30:10.388Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6669
File: www/src/docs/exampleComponents/ScatterChart/ScatterChartWithLabels.tsx:2-2
Timestamp: 2025-11-23T13:30:10.388Z
Learning: The `TooltipIndex` type from recharts is defined in `src/state/tooltipSlice.ts` but is not currently exported from the public API entry points. It should not be imported from `recharts/types/state/tooltipSlice` as this is an internal implementation path. An ESLint rule is needed to prevent regressions.

Applied to files:

  • test/polar/Pie-TwoLevelPieChart.spec.tsx
  • www/src/docs/exampleComponents/PieChart/CustomActiveShapePieChart.tsx
  • src/polar/Pie.tsx
🧬 Code graph analysis (2)
test/polar/Pie-TwoLevelPieChart.spec.tsx (1)
src/polar/Pie.tsx (2)
  • PieSectorDataItem (158-162)
  • Pie (856-896)
src/polar/Pie.tsx (4)
src/util/types.ts (1)
  • DataKey (59-59)
src/state/graphicalItemsSlice.ts (1)
  • GraphicalItemId (19-19)
src/state/selectors/tooltipSelectors.ts (2)
  • selectActiveTooltipDataKey (405-414)
  • selectActiveTooltipCoordinate (435-444)
src/util/useUniqueId.ts (1)
  • WithoutId (37-37)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build, Test, Pack
🔇 Additional comments (4)
test/polar/Pie.spec.tsx (1)

360-406: dataKey assertions in Pie tests correctly reflect the updated sector shape

The added dataKey expectations for:

  • activeShape payload ('y'),
  • PieLabelRenderProps ('value'), and
  • event handler payloads ('uv')

are consistent with PieSectorDataItem now carrying a dataKey and with computePieSectors assigning that field. This keeps the tests aligned with the new public shape of sector data and validates important integration points (labels, tooltips, and events).

Also applies to: 500-555, 1862-1901, 1939-2035, 2069-2111

test/state/selectors/pieSelectors.spec.tsx (1)

47-377: Selector expectations for dataKey are consistent with updated PieSectorDataItem

The updated expected results now asserting dataKey:

  • 'uv' before the dataKey toggle,
  • 'pv' after toggling, and
  • 'value' for the custom-data test,

match the <Pie> configuration and the new PieSectorDataItem shape. This gives good coverage that selectPieSectors reflects the current dataKey and that the additional field doesn’t interfere with the spread of arbitrary payload properties.

Also applies to: 389-719, 752-848

test/polar/Pie-TwoLevelPieChart.spec.tsx (1)

1-126: Two-level Pie tests accurately capture the active-shape regression and its fix

Both tests exercise the core scenarios:

  • Two pies sharing dataKey="value" now yield exactly one active shape for whichever sector is hovered, and clear correctly on mouse out.
  • Pies with different dataKeys (uv vs pv) still activate the right sector independently.

This gives solid regression coverage for the cross-highlighting issue in multi-Pie charts and validates the new coordinate+dataKey-based activation behavior.

src/polar/Pie.tsx (1)

135-146: Propagating dataKey into PieSectorDataItem and computePieSectors looks correct

Adding dataKey?: DataKey<any> to PieSectorData and then assigning dataKey inside computePieSectors ensures each PieSectorDataItem carries the source dataKey:

  • Tooltip payloads and selector outputs now have a stable dataKey to assert on.
  • Event handlers and labels receive sector props that include the same dataKey the <Pie> was configured with (string or function), matching the updated tests.

The wiring from PieSettings.dataKey through computePieSectors to sector objects is consistent and preserves behavior for the default 'value' dataKey.

Also applies to: 560-635

Comment on lines +1 to 3
import { Pie, PieChart, Sector, Tooltip } from 'recharts';
import { PieSectorDataItem } from 'recharts/types/polar/Pie';
import { TooltipIndex } from 'recharts/types/state/tooltipSlice';
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use shared PieSectorDataItem type, but avoid importing TooltipIndex from an internal path

Typing renderActiveShape with the exported PieSectorDataItem keeps this example aligned with the actual sector props and is a solid improvement.

However, TooltipIndex is imported from 'recharts/types/state/tooltipSlice', which is an internal implementation path and not part of the public API surface. Using it in a public-facing docs example encourages consumers to rely on unsupported deep imports.

For this example component, consider either:

  • Typing defaultIndex more generically (e.g. number | undefined) or with a small local union that reflects the supported values, or
  • Re-exporting TooltipIndex from the main recharts entry point and importing it from there before using it in docs.

Based on learnings, this avoids leaking internal state types into public examples.

Also applies to: 71-77

@codecov
Copy link

codecov bot commented Nov 23, 2025

Codecov Report

❌ Patch coverage is 94.59459% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.02%. Comparing base (0710526) to head (f7d87e5).
⚠️ Report is 9 commits behind head on main.

Files with missing lines Patch % Lines
src/state/selectors/tooltipSelectors.ts 77.77% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6678      +/-   ##
==========================================
- Coverage   94.02%   94.02%   -0.01%     
==========================================
  Files         499      499              
  Lines       42547    42577      +30     
  Branches     4873     4878       +5     
==========================================
+ Hits        40004    40032      +28     
- Misses       2538     2540       +2     
  Partials        5        5              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@shreedharbhat98 shreedharbhat98 changed the title fix(Pie): prevent cross-highlighting in multi-Pie charts with shared … fix(Pie): prevent cross-highlighting in multi-Pie charts with shared dataKey Nov 23, 2025
Copy link
Member

@ckifer ckifer left a comment

Choose a reason for hiding this comment

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

This might be a good interim but I don't really think this works long term - can you give a different approach a try and if it doesn't work we can merge this for now?

// For Pie charts, when multiple Pies share the same dataKey, we need to ensure only the hovered Pie's sector is active.
// We do this by checking if the active tooltip coordinate matches this sector's tooltip position.
// This works because each sector has a unique tooltip position based on its midAngle and middleRadius.
const coordinateMatches =
Copy link
Member

Choose a reason for hiding this comment

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

This will lead to issues down the road if we ever want to support Pie tooltips that are not a fixed position. I wonder if there is a way to use graphicalItemId here to identify what pie is being hovered. Can we add graphicalItemId to the active item state?

Copy link
Collaborator

Choose a reason for hiding this comment

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

+1 let's have this based on the graphical item ID.

Copy link
Contributor Author

@shreedharbhat98 shreedharbhat98 Nov 26, 2025

Choose a reason for hiding this comment

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

@ckifer I have made the necessary changes and upadted stackblitz link as well. Please do take a look
Thanks!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
test/component/Tooltip/Tooltip.sync.spec.tsx (1)

446-461: Consider using expectLastCalledWith consistently for spy assertions

This spec already imports expectLastCalledWith, but many tests still use expect(spy).toHaveBeenLastCalledWith(...). Converting those to expectLastCalledWith(spy, ...) would better follow the local testing conventions and keep typings/autocomplete uniform across the suite.

Also applies to: 570-583, 795-901

src/state/tooltipSlice.ts (1)

358-363: Consider propagating activeGraphicalItemId into keyboardInteraction as well

TooltipInteractionState now carries graphicalItemId, and mouse interactions/sync state set it, but setKeyboardInteraction ignores activeGraphicalItemId. If you later support keyboard navigation between multiple graphical items that share the same index/dataKey (e.g. multiple Pies), you may want to store graphicalItemId here too for consistency.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cf2a926 and 814d45f.

📒 Files selected for processing (13)
  • src/context/tooltipContext.tsx (4 hunks)
  • src/state/selectors/combiners/combineTooltipInteractionState.ts (1 hunks)
  • src/state/selectors/tooltipSelectors.ts (1 hunks)
  • src/state/tooltipSlice.ts (6 hunks)
  • src/synchronisation/useChartSynchronisation.tsx (3 hunks)
  • test/cartesian/Bar.spec.tsx (1 hunks)
  • test/chart/ScatterChart.spec.tsx (3 hunks)
  • test/component/Tooltip/Tooltip.sync.spec.tsx (11 hunks)
  • test/component/Tooltip/Tooltip.visibility.spec.tsx (7 hunks)
  • test/polar/Pie.spec.tsx (14 hunks)
  • test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts (1 hunks)
  • test/synchronisation/eventCenter.spec.ts (2 hunks)
  • test/synchronisation/useChartSynchronisation.spec.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/polar/Pie.spec.tsx
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

Run type checking on the codebase using npm run check-types

**/*.{ts,tsx}: Never use any type (implicit or explicit) in TypeScript code
Prefer unknown over any and refine the type in TypeScript
Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions
Do not use as type assertions in TypeScript; the only exception is as const

Files:

  • test/component/Tooltip/Tooltip.visibility.spec.tsx
  • src/state/selectors/tooltipSelectors.ts
  • src/state/selectors/combiners/combineTooltipInteractionState.ts
  • test/synchronisation/eventCenter.spec.ts
  • test/chart/ScatterChart.spec.tsx
  • src/state/tooltipSlice.ts
  • src/synchronisation/useChartSynchronisation.tsx
  • test/cartesian/Bar.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
  • src/context/tooltipContext.tsx
  • test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts
  • test/synchronisation/useChartSynchronisation.spec.tsx
{test,www/test}/**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

Write unit tests in the test or www/test directories with .spec.tsx file extension

Files:

  • test/component/Tooltip/Tooltip.visibility.spec.tsx
  • test/synchronisation/eventCenter.spec.ts
  • test/chart/ScatterChart.spec.tsx
  • test/cartesian/Bar.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
  • test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts
  • test/synchronisation/useChartSynchronisation.spec.tsx
test/**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Aim for 100% unit test code coverage when writing new code

Files:

  • test/component/Tooltip/Tooltip.visibility.spec.tsx
  • test/synchronisation/eventCenter.spec.ts
  • test/chart/ScatterChart.spec.tsx
  • test/cartesian/Bar.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
  • test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts
  • test/synchronisation/useChartSynchronisation.spec.tsx
test/component/**/*.spec.tsx

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use React Testing Library for testing component interactions and behavior upon rendering

Files:

  • test/component/Tooltip/Tooltip.visibility.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Ensure code lints by running npm run lint and follows Airbnb's Style Guide

Files:

  • test/component/Tooltip/Tooltip.visibility.spec.tsx
  • src/state/selectors/tooltipSelectors.ts
  • src/state/selectors/combiners/combineTooltipInteractionState.ts
  • test/synchronisation/eventCenter.spec.ts
  • test/chart/ScatterChart.spec.tsx
  • src/state/tooltipSlice.ts
  • src/synchronisation/useChartSynchronisation.tsx
  • test/cartesian/Bar.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
  • src/context/tooltipContext.tsx
  • test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts
  • test/synchronisation/useChartSynchronisation.spec.tsx
test/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (test/README.md)

test/**/*.{test,spec}.{ts,tsx}: Aim for 100% unit test code coverage when writing new code
Prefer to use the createSelectorTestCase helper function when writing or modifying tests
Use the expectLastCalledWith helper function instead of expect(spy).toHaveBeenLastCalledWith(...) for better typing and autocompletion
Verify the number of selector calls using the spy object from createSelectorTestCase to spot unnecessary re-renders and improve performance
Mock getBoundingClientRect in tests using the helper function provided in test/helper/MockGetBoundingClientRect.ts
Use vi.useFakeTimers() in all tests due to Redux autoBatchEnhancer dependency on timers and requestAnimationFrame
Call vi.runOnlyPendingTimers() to advance timers after renders when not using createSelectorTestCase helper, and avoid vi.runAllTimers() to prevent infinite loops
Use userEvent.setup({ advanceTimers: vi.runOnlyPendingTimers }) or the userEventSetup helper function from test/helper/userEventSetup.ts when creating userEvent instances
When testing tooltips on hover, use vi.runOnlyPendingTimers() after each userEvent.hover() call or use the showTooltip helper function from tooltipTestHelpers.ts to account for requestAnimationFrame delays

Files:

  • test/component/Tooltip/Tooltip.visibility.spec.tsx
  • test/synchronisation/eventCenter.spec.ts
  • test/chart/ScatterChart.spec.tsx
  • test/cartesian/Bar.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
  • test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts
  • test/synchronisation/useChartSynchronisation.spec.tsx
**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

When running unit tests, prefer to run a single test file using npm run test -- path/to/TestFile.spec.tsx rather than running all tests with npm test

Files:

  • test/component/Tooltip/Tooltip.visibility.spec.tsx
  • test/synchronisation/eventCenter.spec.ts
  • test/chart/ScatterChart.spec.tsx
  • test/cartesian/Bar.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
  • test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts
  • test/synchronisation/useChartSynchronisation.spec.tsx
src/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

Run ESLint and Prettier on the codebase using npm run lint

Files:

  • src/state/selectors/tooltipSelectors.ts
  • src/state/selectors/combiners/combineTooltipInteractionState.ts
  • src/state/tooltipSlice.ts
  • src/synchronisation/useChartSynchronisation.tsx
  • src/context/tooltipContext.tsx
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not hardcode any strings or formatting choices in library code; users should provide localized strings as desired

Files:

  • src/state/selectors/tooltipSelectors.ts
  • src/state/selectors/combiners/combineTooltipInteractionState.ts
  • src/state/tooltipSlice.ts
  • src/synchronisation/useChartSynchronisation.tsx
  • src/context/tooltipContext.tsx
🧠 Learnings (7)
📚 Learning: 2025-11-25T01:23:08.237Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.237Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : When testing tooltips on hover, use `vi.runOnlyPendingTimers()` after each `userEvent.hover()` call or use the `showTooltip` helper function from `tooltipTestHelpers.ts` to account for requestAnimationFrame delays

Applied to files:

  • test/component/Tooltip/Tooltip.visibility.spec.tsx
  • src/state/selectors/tooltipSelectors.ts
  • test/chart/ScatterChart.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
  • test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts
  • test/synchronisation/useChartSynchronisation.spec.tsx
📚 Learning: 2025-11-23T13:30:10.388Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6669
File: www/src/docs/exampleComponents/ScatterChart/ScatterChartWithLabels.tsx:2-2
Timestamp: 2025-11-23T13:30:10.388Z
Learning: The `TooltipIndex` type from recharts is defined in `src/state/tooltipSlice.ts` but is not currently exported from the public API entry points. It should not be imported from `recharts/types/state/tooltipSlice` as this is an internal implementation path. An ESLint rule is needed to prevent regressions.

Applied to files:

  • test/component/Tooltip/Tooltip.visibility.spec.tsx
  • src/state/selectors/tooltipSelectors.ts
  • src/state/selectors/combiners/combineTooltipInteractionState.ts
  • test/chart/ScatterChart.spec.tsx
  • src/state/tooltipSlice.ts
  • src/synchronisation/useChartSynchronisation.tsx
  • test/cartesian/Bar.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
  • src/context/tooltipContext.tsx
  • test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts
  • test/synchronisation/useChartSynchronisation.spec.tsx
📚 Learning: 2025-11-25T01:23:08.237Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.237Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Use `userEvent.setup({ advanceTimers: vi.runOnlyPendingTimers })` or the `userEventSetup` helper function from `test/helper/userEventSetup.ts` when creating userEvent instances

Applied to files:

  • test/synchronisation/eventCenter.spec.ts
📚 Learning: 2025-11-25T01:23:08.237Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.237Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Use the `expectLastCalledWith` helper function instead of `expect(spy).toHaveBeenLastCalledWith(...)` for better typing and autocompletion

Applied to files:

  • test/component/Tooltip/Tooltip.sync.spec.tsx
📚 Learning: 2025-11-25T01:23:08.237Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.237Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Verify the number of selector calls using the spy object from `createSelectorTestCase` to spot unnecessary re-renders and improve performance

Applied to files:

  • test/component/Tooltip/Tooltip.sync.spec.tsx
  • test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts
📚 Learning: 2025-11-25T01:23:08.237Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.237Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Prefer to use the `createSelectorTestCase` helper function when writing or modifying tests

Applied to files:

  • test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts
📚 Learning: 2025-11-25T01:23:08.237Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.237Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Call `vi.runOnlyPendingTimers()` to advance timers after renders when not using `createSelectorTestCase` helper, and avoid `vi.runAllTimers()` to prevent infinite loops

Applied to files:

  • test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts
🧬 Code graph analysis (1)
src/state/selectors/tooltipSelectors.ts (3)
src/state/store.ts (1)
  • RechartsRootState (95-95)
src/state/selectors/selectors.ts (1)
  • selectTooltipInteractionState (76-84)
src/state/tooltipSlice.ts (1)
  • TooltipInteractionState (118-162)
🔇 Additional comments (12)
test/synchronisation/useChartSynchronisation.spec.tsx (1)

44-60: Tooltip sync tests correctly assert new graphicalItemId field

Adding graphicalItemId: undefined to the expected setSyncInteraction payloads matches the updated sync state shape and the hook’s behavior (initial emit, hover, and leave). No issues here.

Also applies to: 62-101, 115-141

src/synchronisation/useChartSynchronisation.tsx (1)

95-110: graphicalItemId propagation and reset look consistent in sync listener and emitter

  • Reset path now clears graphicalItemId alongside other fields when sync cannot apply, which keeps state coherent.
  • Derived sync actions forward action.payload.graphicalItemId, and outgoing sync from this hook explicitly sends graphicalItemId: undefined, which matches its axis‑driven role.
    Implementation looks sound.

Also applies to: 120-129, 236-245

test/component/Tooltip/Tooltip.sync.spec.tsx (1)

484-499: Tooltip sync tests correctly include graphicalItemId in interaction state

The added graphicalItemId: undefined fields in setSyncInteraction dispatches and selectSynchronisedTooltipState expectations are consistent with the extended tooltip state and reducer behavior. Shapes and values all line up.

Also applies to: 528-581, 795-901

src/context/tooltipContext.tsx (1)

21-38: Hook changes cleanly thread graphicalItemId into tooltip interaction state

Adding the optional graphicalItemId parameter and passing it as activeGraphicalItemId in both mouse‑enter and click dispatchers is type‑safe, backward‑compatible, and aligns with the extended tooltip slice. Looks good.

Also applies to: 50-67

src/state/tooltipSlice.ts (1)

145-162: Graphical item identification is threaded cleanly through tooltip state and mouse interactions

The new graphicalItemId field is added consistently to TooltipInteractionState, noInteraction, syncInteraction, and the mouse over/click reducers, and the payload type is extended appropriately. This gives you the extra discriminant you need without changing existing semantics.

Also applies to: 180-186, 239-257, 268-273, 307-338

test/cartesian/Bar.spec.tsx (1)

1652-1719: Tooltip state expectation correctly updated for graphicalItemId

Including graphicalItemId: undefined in itemInteraction.hover keeps the test aligned with the new TooltipInteractionState shape while preserving existing behavior for Bar hover.

test/synchronisation/eventCenter.spec.ts (1)

15-48: Sync interaction payload now matches extended tooltip state

Adding graphicalItemId: undefined to the setSyncInteraction payload and expectation correctly reflects the new TooltipSyncState shape without changing test intent.

test/chart/ScatterChart.spec.tsx (1)

1537-1591: Scatter tooltip state tests correctly account for graphicalItemId

The added graphicalItemId: undefined fields in the TooltipState expectations match the expanded interaction state shape and do not alter the behavioral assertions of these tests.

test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts (1)

7-13: Test helper now matches TooltipInteractionState shape

Extending createInteraction with graphicalItemId: undefined is the right way to keep these selector tests aligned with the updated tooltip interaction state type.

test/component/Tooltip/Tooltip.visibility.spec.tsx (1)

1063-1227: Radar tooltip visibility state tests updated appropriately for graphicalItemId

Adding graphicalItemId: undefined across axis, item, keyboard, and sync interaction expectations keeps these visibility tests consistent with the extended tooltip state while preserving their behavioral focus.

src/state/selectors/tooltipSelectors.ts (1)

416-425: New selector selectActiveTooltipGraphicalItemId aligns with existing tooltip selector patterns

This selector cleanly exposes tooltipInteraction.graphicalItemId via createSelector, matching the shape and style of selectActiveTooltipDataKey and fitting well into the existing selector API.

src/state/selectors/combiners/combineTooltipInteractionState.ts (1)

62-69: Default-index interaction state now includes graphicalItemId

Extending the defaultIndex-derived TooltipInteractionState with graphicalItemId: undefined keeps this path consistent with the updated type and other interaction sources.

…dataKey

Fixes recharts#6259

Add coordinate-based matching to ensure only the hovered Pie shows active
sectors when multiple Pies share the same dataKey. Compare tooltip coordinates
with sector positions using 0.01 tolerance for precise Pie identification.

- Add coordinate matching logic in PieSectors component
- Include dataKey in sector data for tracking
- Add tests for TwoLevelPieChart behavior
@shreedharbhat98 shreedharbhat98 force-pushed the fix/pie-active-shape-two-level-chart branch from 814d45f to 2992877 Compare November 25, 2025 18:00
@codecov
Copy link

codecov bot commented Nov 25, 2025

Bundle Report

Changes will increase total bundle size by 1.73kB (0.07%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
recharts/bundle-cjs 1.15MB 1.73kB (0.15%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: recharts/bundle-cjs

Assets Changed:

Asset Name Size Change Total Size Change (%)
polar/Pie.js 881 bytes 26.17kB 3.48%
state/selectors/tooltipSelectors.js 322 bytes 16.72kB 1.96%
synchronisation/useChartSynchronisation.js 129 bytes 12.89kB 1.01%
state/tooltipSlice.js 242 bytes 8.81kB 2.82%
state/selectors/combiners/combineTooltipInteractionState.js 34 bytes 3.35kB 1.02%
context/tooltipContext.js 126 bytes 1.84kB 7.36% ⚠️

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
src/polar/Pie.tsx (2)

323-323: GraphicalItemId plumbed through but unused – either hook into active matching or drop for now

id: GraphicalItemId is added to PieSectorsProps, threaded through SectorsWithAnimation, and passed down from PieImpl, but it is never actually read in PieSectors. As it stands, this extra prop doesn’t change behavior and adds a bit of noise.

Given earlier discussion about basing active state on graphical item identity, this id looks like the right hook to gate isActive on the current Pie instance instead of relying solely on coordinates.

Either (a) complete the wiring by reading id inside PieSectors and combining it with an activeGraphicalItemId from tooltip state when computing isActive, or (b) remove the id parameter from PieSectorsProps/SectorsWithAnimation and the <SectorsWithAnimation ... id={id} /> call until it’s actually used. If you go with (a), adding a focused unit test that verifies only the Pie whose GraphicalItemId matches the active tooltip item becomes active will help guard against regressions.

Also applies to: 728-729, 732-733, 819-820, 887-887


554-566: Active-sector detection tied to tooltip coordinate may conflict with future/non-fixed tooltip positioning

The new coordinateMatches check (with a very tight < 0.01 epsilon) fixes the immediate “multi-Pie with shared dataKey activates all slices” bug by ensuring only the Pie whose tooltipPosition matches the active tooltip coordinate becomes active. However, this also couples isActive to the tooltip’s coordinate:

  • If TooltipInteractionState.coordinate is ever decoupled from the sector center (e.g., custom or movable tooltip positions, or different coordinate strategies across synced charts), coordinateMatches may always be false and no sector will be active even though activeIndex and activeDataKey are set.
  • Prior reviewer feedback already called out preferring a GraphicalItemId-based approach to avoid exactly this coupling; this change doesn’t yet make use of GraphicalItemId even though id is now threaded into PieSectors.

Given that GraphicalItemId is already available, I’d strongly recommend incorporating an “active graphical item” check into isActive (e.g., via an activeGraphicalItemId selector) and relying primarily on id + activeIndex + activeDataKey for matching, using coordinates only as a fallback if needed. That would both solve the multi-Pie bug and avoid blocking future work on non-fixed Pie tooltips. Please confirm whether tooltip state already exposes graphicalItemId; if so, we can wire it into PieSectors now, otherwise this PR might be a good place to add that selector.

🧹 Nitpick comments (1)
src/polar/Pie.tsx (1)

135-145: Propagating dataKey into PieSectorDataItem is reasonable but overrides user dataKey fields

Adding dataKey?: DataKey<any> to PieSectorData and then assigning dataKey inside computePieSectors ensures each sector carries the Pie’s dataKey, which is helpful for selectors and debugging.

Because entryWithCellInfo is spread before dataKey, any dataKey field present on the original data objects will now be overwritten by the chart’s dataKey. That’s probably what we want (sector dataKey matches the accessor used), but it is a subtle behavioral change for users who previously relied on a dataKey property in their data payloads.

Consider either documenting this override behavior for PieSectorDataItem.dataKey, or, if preserving payload dataKey is important, renaming this field to something less likely to collide (e.g., sectorDataKey) and updating the selectors accordingly. A quick repo search for consumers of PieSectorDataItem['dataKey'] can confirm current expectations.

Also applies to: 660-677

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 814d45f and 2992877.

📒 Files selected for processing (17)
  • src/context/tooltipContext.tsx (4 hunks)
  • src/polar/Pie.tsx (9 hunks)
  • src/state/selectors/combiners/combineTooltipInteractionState.ts (1 hunks)
  • src/state/selectors/tooltipSelectors.ts (1 hunks)
  • src/state/tooltipSlice.ts (6 hunks)
  • src/synchronisation/useChartSynchronisation.tsx (3 hunks)
  • test/cartesian/Bar.spec.tsx (1 hunks)
  • test/chart/ScatterChart.spec.tsx (3 hunks)
  • test/component/Tooltip/Tooltip.sync.spec.tsx (11 hunks)
  • test/component/Tooltip/Tooltip.visibility.spec.tsx (7 hunks)
  • test/polar/Pie-TwoLevelPieChart.spec.tsx (1 hunks)
  • test/polar/Pie.spec.tsx (14 hunks)
  • test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts (1 hunks)
  • test/state/selectors/pieSelectors.spec.tsx (16 hunks)
  • test/synchronisation/eventCenter.spec.ts (2 hunks)
  • test/synchronisation/useChartSynchronisation.spec.tsx (4 hunks)
  • www/src/docs/exampleComponents/PieChart/CustomActiveShapePieChart.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts
  • www/src/docs/exampleComponents/PieChart/CustomActiveShapePieChart.tsx
  • test/component/Tooltip/Tooltip.visibility.spec.tsx
  • test/synchronisation/useChartSynchronisation.spec.tsx
  • src/context/tooltipContext.tsx
  • test/synchronisation/eventCenter.spec.ts
  • test/cartesian/Bar.spec.tsx
  • test/polar/Pie-TwoLevelPieChart.spec.tsx
🧰 Additional context used
📓 Path-based instructions (9)
src/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

Run ESLint and Prettier on the codebase using npm run lint

Files:

  • src/state/tooltipSlice.ts
  • src/state/selectors/tooltipSelectors.ts
  • src/polar/Pie.tsx
  • src/synchronisation/useChartSynchronisation.tsx
  • src/state/selectors/combiners/combineTooltipInteractionState.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

Run type checking on the codebase using npm run check-types

**/*.{ts,tsx}: Never use any type (implicit or explicit) in TypeScript code
Prefer unknown over any and refine the type in TypeScript
Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions
Do not use as type assertions in TypeScript; the only exception is as const

Files:

  • src/state/tooltipSlice.ts
  • src/state/selectors/tooltipSelectors.ts
  • test/polar/Pie.spec.tsx
  • test/chart/ScatterChart.spec.tsx
  • src/polar/Pie.tsx
  • src/synchronisation/useChartSynchronisation.tsx
  • src/state/selectors/combiners/combineTooltipInteractionState.ts
  • test/state/selectors/pieSelectors.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Ensure code lints by running npm run lint and follows Airbnb's Style Guide

Files:

  • src/state/tooltipSlice.ts
  • src/state/selectors/tooltipSelectors.ts
  • test/polar/Pie.spec.tsx
  • test/chart/ScatterChart.spec.tsx
  • src/polar/Pie.tsx
  • src/synchronisation/useChartSynchronisation.tsx
  • src/state/selectors/combiners/combineTooltipInteractionState.ts
  • test/state/selectors/pieSelectors.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not hardcode any strings or formatting choices in library code; users should provide localized strings as desired

Files:

  • src/state/tooltipSlice.ts
  • src/state/selectors/tooltipSelectors.ts
  • src/polar/Pie.tsx
  • src/synchronisation/useChartSynchronisation.tsx
  • src/state/selectors/combiners/combineTooltipInteractionState.ts
{test,www/test}/**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

Write unit tests in the test or www/test directories with .spec.tsx file extension

Files:

  • test/polar/Pie.spec.tsx
  • test/chart/ScatterChart.spec.tsx
  • test/state/selectors/pieSelectors.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
test/**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Aim for 100% unit test code coverage when writing new code

Files:

  • test/polar/Pie.spec.tsx
  • test/chart/ScatterChart.spec.tsx
  • test/state/selectors/pieSelectors.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
test/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (test/README.md)

test/**/*.{test,spec}.{ts,tsx}: Aim for 100% unit test code coverage when writing new code
Prefer to use the createSelectorTestCase helper function when writing or modifying tests
Use the expectLastCalledWith helper function instead of expect(spy).toHaveBeenLastCalledWith(...) for better typing and autocompletion
Verify the number of selector calls using the spy object from createSelectorTestCase to spot unnecessary re-renders and improve performance
Mock getBoundingClientRect in tests using the helper function provided in test/helper/MockGetBoundingClientRect.ts
Use vi.useFakeTimers() in all tests due to Redux autoBatchEnhancer dependency on timers and requestAnimationFrame
Call vi.runOnlyPendingTimers() to advance timers after renders when not using createSelectorTestCase helper, and avoid vi.runAllTimers() to prevent infinite loops
Use userEvent.setup({ advanceTimers: vi.runOnlyPendingTimers }) or the userEventSetup helper function from test/helper/userEventSetup.ts when creating userEvent instances
When testing tooltips on hover, use vi.runOnlyPendingTimers() after each userEvent.hover() call or use the showTooltip helper function from tooltipTestHelpers.ts to account for requestAnimationFrame delays

Files:

  • test/polar/Pie.spec.tsx
  • test/chart/ScatterChart.spec.tsx
  • test/state/selectors/pieSelectors.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

When running unit tests, prefer to run a single test file using npm run test -- path/to/TestFile.spec.tsx rather than running all tests with npm test

Files:

  • test/polar/Pie.spec.tsx
  • test/chart/ScatterChart.spec.tsx
  • test/state/selectors/pieSelectors.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
test/component/**/*.spec.tsx

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use React Testing Library for testing component interactions and behavior upon rendering

Files:

  • test/component/Tooltip/Tooltip.sync.spec.tsx
🧠 Learnings (5)
📚 Learning: 2025-11-23T13:30:10.388Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6669
File: www/src/docs/exampleComponents/ScatterChart/ScatterChartWithLabels.tsx:2-2
Timestamp: 2025-11-23T13:30:10.388Z
Learning: The `TooltipIndex` type from recharts is defined in `src/state/tooltipSlice.ts` but is not currently exported from the public API entry points. It should not be imported from `recharts/types/state/tooltipSlice` as this is an internal implementation path. An ESLint rule is needed to prevent regressions.

Applied to files:

  • src/state/tooltipSlice.ts
  • src/state/selectors/tooltipSelectors.ts
  • test/polar/Pie.spec.tsx
  • test/chart/ScatterChart.spec.tsx
  • src/polar/Pie.tsx
  • src/synchronisation/useChartSynchronisation.tsx
  • src/state/selectors/combiners/combineTooltipInteractionState.ts
  • test/component/Tooltip/Tooltip.sync.spec.tsx
📚 Learning: 2025-11-25T01:23:08.237Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.237Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : When testing tooltips on hover, use `vi.runOnlyPendingTimers()` after each `userEvent.hover()` call or use the `showTooltip` helper function from `tooltipTestHelpers.ts` to account for requestAnimationFrame delays

Applied to files:

  • src/state/selectors/tooltipSelectors.ts
  • test/polar/Pie.spec.tsx
  • test/chart/ScatterChart.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
📚 Learning: 2025-11-25T01:23:08.237Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.237Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Verify the number of selector calls using the spy object from `createSelectorTestCase` to spot unnecessary re-renders and improve performance

Applied to files:

  • test/polar/Pie.spec.tsx
  • test/state/selectors/pieSelectors.spec.tsx
  • test/component/Tooltip/Tooltip.sync.spec.tsx
📚 Learning: 2025-11-25T01:23:08.237Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.237Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Prefer to use the `createSelectorTestCase` helper function when writing or modifying tests

Applied to files:

  • test/state/selectors/pieSelectors.spec.tsx
📚 Learning: 2025-11-25T01:23:08.237Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.237Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Use the `expectLastCalledWith` helper function instead of `expect(spy).toHaveBeenLastCalledWith(...)` for better typing and autocompletion

Applied to files:

  • test/component/Tooltip/Tooltip.sync.spec.tsx
🧬 Code graph analysis (2)
src/state/selectors/tooltipSelectors.ts (3)
src/state/store.ts (1)
  • RechartsRootState (95-95)
src/state/selectors/selectors.ts (1)
  • selectTooltipInteractionState (76-84)
src/state/tooltipSlice.ts (1)
  • TooltipInteractionState (118-162)
src/polar/Pie.tsx (4)
src/util/types.ts (1)
  • DataKey (60-60)
src/state/graphicalItemsSlice.ts (1)
  • GraphicalItemId (19-19)
src/state/selectors/tooltipSelectors.ts (2)
  • selectActiveTooltipDataKey (405-414)
  • selectActiveTooltipCoordinate (446-455)
src/util/useUniqueId.ts (1)
  • WithoutId (37-37)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build, Test, Pack
🔇 Additional comments (10)
src/synchronisation/useChartSynchronisation.tsx (1)

95-107: Graphical item id propagation in tooltip sync is consistent

graphicalItemId is correctly reset when clearing sync state, preserved from incoming sync payloads, and intentionally omitted (set to undefined) from locally-originated sync actions. This keeps the sync protocol stable while allowing the richer local state.

Also applies to: 120-128, 236-244

src/state/tooltipSlice.ts (1)

118-162: Tooltip interaction now cleanly supports filtering by graphical item id

The new graphicalItemId field is threaded through the type, initial state, and the hover/click item reducers, and is explicitly set in both noInteraction and syncInteraction. All object literals that construct a TooltipInteractionState include this field, so the shape stays consistent and there are no dangling undefined properties beyond what’s intended.

Also applies to: 180-186, 239-257, 268-273, 307-315, 330-337

test/chart/ScatterChart.spec.tsx (1)

1535-1591: Scatter tooltip state expectations correctly updated for graphicalItemId

The tooltip state snapshots now include graphicalItemId: undefined for all interaction buckets, matching the extended TooltipInteractionState/TooltipState shape. This keeps the tests aligned with the store without altering semantics.

src/state/selectors/tooltipSelectors.ts (1)

416-425: New selector for active graphical item id mirrors existing dataKey selector

selectActiveTooltipGraphicalItemId follows the same pattern as selectActiveTooltipDataKey, guarding against an undefined interaction state and simply exposing tooltipInteraction.graphicalItemId. This is a minimal, correct extension of the selector surface.

test/polar/Pie.spec.tsx (2)

334-412: Pie sector tests now validate dataKey propagation across shapes and events

The expectations for activeShape props, label render props, and click/hover/touch event payloads now include the sector dataKey ('y', 'value', 'uv' as appropriate). This gives good coverage that the new field is consistently present in all Pie-sector-facing APIs.

Also applies to: 505-552, 1872-1918, 1949-1995, 2003-2052, 2079-2128


789-807: Pie tooltip state snapshots updated for graphicalItemId

The tooltip itemInteraction expectations now include graphicalItemId: undefined for both click and hover, including defaultIndex and touch-driven cases. This keeps Pie’s tooltip tests in sync with the widened tooltip state.

Also applies to: 819-836, 1042-1078, 1438-1451

test/component/Tooltip/Tooltip.sync.spec.tsx (1)

487-495: Tooltip synchronization tests correctly account for graphicalItemId in syncInteraction

Every setSyncInteraction payload and synchronised tooltip state expectation now includes graphicalItemId: undefined, aligning with the extended TooltipSyncState. The synchronization semantics (active flags, coordinates, index, label, sourceViewBox) remain unchanged and are still thoroughly exercised.

Also applies to: 531-539, 572-580, 799-899

src/state/selectors/combiners/combineTooltipInteractionState.ts (1)

62-69: Default-index tooltip interaction initializes graphicalItemId explicitly

In the defaultIndex != null path, the constructed TooltipInteractionState now includes graphicalItemId: undefined, which keeps it structurally consistent with the updated type and other initial-state paths.

test/state/selectors/pieSelectors.spec.tsx (1)

47-377: Pie selector tests now assert per-sector dataKey in PieSectorDataItem

expectedResultBefore, expectedResultAfter, and the custom-data test all include a dataKey on each PieSectorDataItem, matching the Pie’s dataKey ('uv', 'pv', 'value'). This confirms the selector exposes the new field correctly without changing any other expectations.

Also applies to: 389-719, 751-848

src/polar/Pie.tsx (1)

37-41: Tooltip selectors wiring looks correct and consistent

Importing and using selectActiveTooltipIndex, selectActiveTooltipDataKey, and selectActiveTooltipCoordinate keeps PieSectors aligned with the canonical tooltip state instead of re-deriving it locally. All three selectors are exercised and participate in isActive, with no obvious typing or lifecycle issues in this file.

Please double‑check that the return types and semantics of these selectors (especially selectActiveTooltipIndex being string vs number, and selectActiveTooltipCoordinate never being null in normal Pie interactions) are covered by existing tests around pie tooltips and active shapes.

Also applies to: 531-534

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2992877 and f7d87e5.

📒 Files selected for processing (2)
  • src/polar/Pie.tsx (9 hunks)
  • test/polar/Pie.spec.tsx (14 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/polar/Pie.spec.tsx
🧰 Additional context used
📓 Path-based instructions (4)
src/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

Run ESLint and Prettier on the codebase using npm run lint

Files:

  • src/polar/Pie.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

Run type checking on the codebase using npm run check-types

**/*.{ts,tsx}: Never use any type (implicit or explicit) in TypeScript code
Prefer unknown over any and refine the type in TypeScript
Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions
Do not use as type assertions in TypeScript; the only exception is as const

Files:

  • src/polar/Pie.tsx
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Ensure code lints by running npm run lint and follows Airbnb's Style Guide

Files:

  • src/polar/Pie.tsx
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not hardcode any strings or formatting choices in library code; users should provide localized strings as desired

Files:

  • src/polar/Pie.tsx
🧠 Learnings (1)
📚 Learning: 2025-11-23T13:30:10.388Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6669
File: www/src/docs/exampleComponents/ScatterChart/ScatterChartWithLabels.tsx:2-2
Timestamp: 2025-11-23T13:30:10.388Z
Learning: The `TooltipIndex` type from recharts is defined in `src/state/tooltipSlice.ts` but is not currently exported from the public API entry points. It should not be imported from `recharts/types/state/tooltipSlice` as this is an internal implementation path. An ESLint rule is needed to prevent regressions.

Applied to files:

  • src/polar/Pie.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build, Test, Pack
🔇 Additional comments (5)
src/polar/Pie.tsx (5)

37-41: LGTM: Necessary imports for graphical item tracking.

The new selectors enable proper multi-pie coordination by accessing activeDataKey, activeGraphicalItemId, and activeIndex separately from the tooltip state.


322-322: LGTM: Essential addition for graphical item tracking.

Adding id to PieSectorsProps enables proper identification of which Pie component is being interacted with, addressing the cross-highlighting issue.


667-667: LGTM: Necessary data propagation for multi-pie coordination.

Adding dataKey to the sector data enables the matching logic in PieSectors to correctly identify which sectors belong to which Pie when multiple Pies share the same dataKey.


723-727: LGTM: Proper ID propagation through component hierarchy.

The id parameter is correctly threaded through SectorsWithAnimationPieSectors → event handlers, enabling each Pie component to maintain its own active state independently.

Also applies to: 814-814, 882-882


529-561: Based on the web search results, I now have enough context to rewrite the review comment. The search results clarify:

  1. activeIndex type: It can be number | string (TooltipIndex union) depending on version, so the String(i) conversion is justified
  2. Coordinate-based matching: The 0.01-pixel tolerance is a known pattern for Recharts tooltips, but may not be necessary when using graphicalItemId matching
  3. Implementation approach: The graphicalItemId-based matching is a valid approach for multi-pie scenarios

Graphical item matching logic correctly implements the required fix for multi-pie cross-highlighting.

The implementation properly addresses the cross-highlighting issue by checking if the active graphical item ID matches this Pie's ID. The null checks provide backward compatibility when graphicalItemId is undefined.

The String(i) === activeIndex comparison is appropriate because activeIndex can be a string or number (TooltipIndex union type in Recharts) depending on the redux state, making the string conversion necessary and intentional.

However, verify whether coordinate-based matching (0.01-pixel tolerance mentioned in the PR description) should also be implemented. The current implementation uses graphicalItemId matching alone, which is a simpler and sufficient approach for multi-pie scenarios. Coordinate-based matching would only be needed if you want fallback matching when graphicalItemIds are unavailable.

No changes required if graphicalItemId matching meets the requirements.


export type PieSectorData = GeometrySector & {
dataKey?: string;
dataKey?: DataKey<any>;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Type uses any in violation of coding guidelines.

The coding guidelines state: "Never use any type (implicit or explicit) in TypeScript code. Prefer unknown over any."

Consider whether DataKey<unknown> would be more appropriate here:

-  dataKey?: DataKey<any>;
+  dataKey?: DataKey<unknown>;

This would need verification across the codebase to ensure type compatibility.

As per coding guidelines, any types should be avoided.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
dataKey?: DataKey<any>;
dataKey?: DataKey<unknown>;
🤖 Prompt for AI Agents
In src/polar/Pie.tsx around line 135, the prop type declared as DataKey<any>
violates the no-any rule; change it to DataKey<unknown> and update any affected
usages: adjust function signatures and callers to accept DataKey<unknown>, add
explicit type guards or narrow/cast values where the concrete type is required,
and run TypeScript compilation and tests to find and fix remaining
incompatibilities across the codebase.

Copy link
Member

@ckifer ckifer left a comment

Choose a reason for hiding this comment

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

nice!

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.

TwoLevelPieChart with activeShape does not work as expected

3 participants