Skip to content

Commit

Permalink
Activeshape mouseleave fix (#4527)
Browse files Browse the repository at this point in the history
  • Loading branch information
PavelVanecek committed May 14, 2024
1 parent f260ab4 commit 10ede6f
Show file tree
Hide file tree
Showing 11 changed files with 239 additions and 214 deletions.
4 changes: 2 additions & 2 deletions src/cartesian/Bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ function BarRectangles(props: BarRectanglesProps) {
const baseProps = filterProps(rest, false);
const { data, shape, dataKey, activeBar } = props;

const { index: activeIndex } = useTooltipContext();
const { index: activeIndex, active: isTooltipActive } = useTooltipContext();
const {
onMouseEnter: onMouseEnterFromProps,
onClick: onItemClickFromProps,
Expand All @@ -264,7 +264,7 @@ function BarRectangles(props: BarRectanglesProps) {
return (
<>
{data.map((entry, i) => {
const isActive = activeBar && i === activeIndex;
const isActive = isTooltipActive && activeBar && i === activeIndex;
const option = isActive ? activeBar : shape;
const barRectangleProps = {
...baseProps,
Expand Down
4 changes: 2 additions & 2 deletions src/cartesian/Scatter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ function ScatterSymbols(props: ScatterSymbolsProps) {
const { shape, activeShape } = allOtherScatterProps;
const baseProps = filterProps(allOtherScatterProps, false);

const { index: activeIndex } = useTooltipContext();
const { index: activeIndex, active: isTooltipActive } = useTooltipContext();
const {
onMouseEnter: onMouseEnterFromProps,
onClick: onItemClickFromProps,
Expand All @@ -156,7 +156,7 @@ function ScatterSymbols(props: ScatterSymbolsProps) {
return (
<>
{points.map((entry, i) => {
const isActive = activeShape && activeIndex === i;
const isActive = isTooltipActive && activeShape && activeIndex === i;
const option = isActive ? activeShape : shape;
const symbolProps = { key: `symbol-${i}`, ...baseProps, ...entry };

Expand Down
2 changes: 1 addition & 1 deletion src/context/tooltipContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const doNotDisplayTooltip: TooltipContextValue = {
payload: [],
coordinate: { x: 0, y: 0 },
active: false,
index: 0,
index: -1,
};

const TooltipContext = createContext<TooltipContextValue>(doNotDisplayTooltip);
Expand Down
4 changes: 2 additions & 2 deletions src/polar/Pie.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ type PieSectorsProps = {
function PieSectors(props: PieSectorsProps) {
const { sectors, sectorRefs, activeShape, blendStroke, inactiveShape: inactiveShapeProp, allOtherPieProps } = props;

const { index: activeIndex } = useTooltipContext();
const { index: activeIndex, active: isTooltipActive } = useTooltipContext();
const {
onMouseEnter: onMouseEnterFromProps,
onClick: onItemClickFromProps,
Expand All @@ -212,7 +212,7 @@ function PieSectors(props: PieSectorsProps) {

return sectors.map((entry, i) => {
if (entry?.startAngle === 0 && entry?.endAngle === 0 && sectors.length !== 1) return null;
const isSectorActive = activeShape && i === activeIndex;
const isSectorActive = isTooltipActive && activeShape && i === activeIndex;
const inactiveShape = activeIndex === -1 ? null : inactiveShapeProp;
const sectorOptions = isSectorActive ? activeShape : inactiveShape;
const sectorProps = {
Expand Down
4 changes: 2 additions & 2 deletions src/polar/RadialBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function RadialBarSectors(props: RadialBarSectorsProps) {
const { shape, activeShape, cornerRadius, ...others } = allOtherRadialBarProps;
const baseProps = filterProps(others, false);

const { index: activeIndex } = useTooltipContext();
const { index: activeIndex, active: isTooltipActive } = useTooltipContext();
const {
onMouseEnter: onMouseEnterFromProps,
onClick: onItemClickFromProps,
Expand All @@ -79,7 +79,7 @@ function RadialBarSectors(props: RadialBarSectorsProps) {
return (
<>
{sectors.map((entry, i) => {
const isActive = activeShape && i === activeIndex;
const isActive = isTooltipActive && activeShape && i === activeIndex;
const onMouseEnter = (e: React.MouseEvent<SVGPathElement, MouseEvent>) => {
// @ts-expect-error the types need a bit of attention
onMouseEnterFromContext(entry, i, e);
Expand Down
47 changes: 17 additions & 30 deletions test/chart/BarChart.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ type DataType = {
pv: number;
};

function assertActiveBarInteractions(container: HTMLElement) {
const chart = container.querySelector('.recharts-wrapper');
assertNotNull(chart);

fireEvent.mouseOver(chart, { clientX: 100, clientY: 100 });
expect(container.querySelectorAll('.recharts-active-bar')).toHaveLength(1);

fireEvent.mouseOut(chart);
expect(container.querySelectorAll('.recharts-active-bar')).toHaveLength(0);
}

describe('<BarChart />', () => {
const data: DataType[] = [
{ name: 'food', uv: 400, pv: 2400 },
Expand Down Expand Up @@ -169,13 +180,7 @@ describe('<BarChart />', () => {
</div>,
);

const chart = container.querySelector('.recharts-wrapper');
assertNotNull(chart);
fireEvent.mouseOver(chart, { clientX: 100, clientY: 100 });

vi.advanceTimersByTime(100);
const bar = container.querySelectorAll('.recharts-active-bar');
expect(bar).toHaveLength(1);
assertActiveBarInteractions(container);
});

test('Renders customized active bar when activeBar set to be a ReactElement', () => {
Expand All @@ -189,13 +194,7 @@ describe('<BarChart />', () => {
</div>,
);

const chart = container.querySelector('.recharts-wrapper');
assertNotNull(chart);
fireEvent.mouseOver(chart, { clientX: 100, clientY: 100 });
vi.advanceTimersByTime(100);

const bar = container.querySelectorAll('.recharts-active-bar');
expect(bar).toHaveLength(1);
assertActiveBarInteractions(container);
});

test('Renders customized active bar when activeBar is set to be a truthy boolean', () => {
Expand All @@ -209,13 +208,7 @@ describe('<BarChart />', () => {
</div>,
);

const chart = container.querySelector('.recharts-wrapper');
assertNotNull(chart);
fireEvent.mouseOver(chart, { clientX: 100, clientY: 100 });

vi.advanceTimersByTime(100);
const bar = container.querySelectorAll('.recharts-active-bar');
expect(bar).toHaveLength(1);
assertActiveBarInteractions(container);
});

test('Does not render customized active bar when activeBar set to be a falsy boolean', () => {
Expand Down Expand Up @@ -248,13 +241,7 @@ describe('<BarChart />', () => {
</div>,
);

const chart = container.querySelector('.recharts-wrapper');
assertNotNull(chart);
fireEvent.mouseOver(chart, { clientX: 100, clientY: 100 });

vi.advanceTimersByTime(100);
const bar = container.querySelectorAll('.recharts-active-bar');
expect(bar).toHaveLength(1);
assertActiveBarInteractions(container);
});

test('Render empty when data is empty', () => {
Expand All @@ -266,7 +253,7 @@ describe('<BarChart />', () => {
expect(container.querySelectorAll('path')).toHaveLength(0);
});

test('Render customized shapem when shape is set to be a react element', () => {
test('Render customized shape when shape is set to be a react element', () => {
const Shape = (props: any) => {
const { x, y } = props;

Expand All @@ -280,7 +267,7 @@ describe('<BarChart />', () => {
expect(container.querySelectorAll('.customized-shape')).toHaveLength(4);
});

test('Render customized shapem when shape is set to be a function', () => {
test('Render customized shape when shape is set to be a function', () => {
const renderShape = (props: BarProps): React.ReactElement => {
const { x, y } = props;

Expand Down
48 changes: 22 additions & 26 deletions test/chart/PieChart.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@ import {
} from '../../src';
import { testChartLayoutContext } from '../util/context';

function assertActiveShapeInteractions(container: HTMLElement, selectors: string) {
const sectorNodes = container.querySelectorAll('.recharts-pie-sector');
expect(sectorNodes.length).toBeGreaterThanOrEqual(2);
const [sector1, sector2] = Array.from(sectorNodes);

fireEvent.mouseOver(sector1, { pageX: 200, pageY: 200 });
expect(container.querySelectorAll(selectors)).toHaveLength(1);

fireEvent.mouseOver(sector2, { pageX: 200, pageY: 200 });
expect(container.querySelectorAll(selectors)).toHaveLength(1);

fireEvent.mouseOut(sector2);
expect(container.querySelectorAll(selectors)).toHaveLength(0);
}

describe('<PieChart />', () => {
const data = [
{ name: 'Group A', value: 400, v: 89 },
Expand Down Expand Up @@ -102,13 +117,9 @@ describe('<PieChart />', () => {
<Tooltip />
</PieChart>,
);
const sectorNodes = container.querySelectorAll('.recharts-pie-sector');
const [sector] = Array.from(sectorNodes);
fireEvent.mouseOver(sector, { pageX: 200, pageY: 200 });

const activeSector = container.querySelectorAll('.recharts-active-shape');
expect(activeSector).toHaveLength(1);
expect(container.querySelectorAll('.customized-active-shape')).toHaveLength(1);
assertActiveShapeInteractions(container, '.recharts-active-shape');
assertActiveShapeInteractions(container, '.customized-active-shape');
});

test('With Tooltip render customized active sector when activeShape is set to be a function', () => {
Expand All @@ -129,13 +140,8 @@ describe('<PieChart />', () => {
</PieChart>,
);

const sectorNodes = container.querySelectorAll('.recharts-pie-sector');
const [sector] = Array.from(sectorNodes);
fireEvent.mouseOver(sector, { pageX: 200, pageY: 200 });

const activeSector = container.querySelectorAll('.recharts-active-shape');
expect(activeSector).toHaveLength(1);
expect(container.querySelectorAll('.customized-active-shape')).toHaveLength(1);
assertActiveShapeInteractions(container, '.recharts-active-shape');
assertActiveShapeInteractions(container, '.customized-active-shape');
});

test('With Tooltip render customized active sector when activeShape is set to be an object', () => {
Expand All @@ -156,13 +162,8 @@ describe('<PieChart />', () => {
</PieChart>,
);

const sectorNodes = container.querySelectorAll('.recharts-pie-sector');
const [sector] = Array.from(sectorNodes);
fireEvent.mouseOver(sector, { pageX: 100, pageY: 100 });

const activeSector = container.querySelectorAll('.recharts-active-shape');
expect(activeSector).toHaveLength(1);
expect(container.querySelectorAll('.customized-active-shape')).toHaveLength(1);
assertActiveShapeInteractions(container, '.recharts-active-shape');
assertActiveShapeInteractions(container, '.customized-active-shape');
});

test('With Tooltip render customized active sector when activeShape is set to be a truthy boolean', () => {
Expand All @@ -183,12 +184,7 @@ describe('<PieChart />', () => {
</PieChart>,
);

const sectorNodes = container.querySelectorAll('.recharts-pie-sector');
const [sector] = Array.from(sectorNodes);
fireEvent.mouseOver(sector, { pageX: 100, pageY: 100 });

const activeSector = container.querySelectorAll('.recharts-active-shape');
expect(activeSector).toHaveLength(1);
assertActiveShapeInteractions(container, '.recharts-active-shape');
});

test('Renders 6 sectors circles when add Cell to specified props of each slice', () => {
Expand Down
44 changes: 19 additions & 25 deletions test/chart/RadialBarChart.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ import {
} from '../../src';
import { testChartLayoutContext } from '../util/context';

function assertActiveShapeInteractions(container: HTMLElement) {
const sectorNodes = container.querySelectorAll('.recharts-sector');
expect(sectorNodes.length).toBeGreaterThanOrEqual(2);
const [sector1, sector2] = Array.from(sectorNodes);

fireEvent.mouseOver(sector1, { clientX: 200, clientY: 200 });
expect(container.querySelectorAll('.recharts-active-shape')).toHaveLength(1);

fireEvent.mouseOver(sector2, { clientX: 200, clientY: 200 });
expect(container.querySelectorAll('.recharts-active-shape')).toHaveLength(1);

fireEvent.mouseOut(sector2);
expect(container.querySelectorAll('.recharts-active-shape')).toHaveLength(0);
}

describe('<RadialBarChart />', () => {
const data = [
{ name: '18-24', uv: 31.47, pv: 2400, fill: '#8884d8' },
Expand Down Expand Up @@ -256,12 +271,7 @@ describe('<RadialBarChart />', () => {
</RadialBarChart>,
);

const sectorNodes = container.querySelectorAll('.recharts-sector');
const [sector] = Array.from(sectorNodes);
fireEvent.mouseOver(sector, { clientX: 200, clientY: 200 });

const activeSector = container.querySelectorAll('.recharts-active-shape');
expect(activeSector).toHaveLength(1);
assertActiveShapeInteractions(container);
});

test('Renders customized active bar when activeBar set to be a ReactElement', () => {
Expand All @@ -281,12 +291,7 @@ describe('<RadialBarChart />', () => {
</RadialBarChart>,
);

const sectorNodes = container.querySelectorAll('.recharts-sector');
const [sector] = Array.from(sectorNodes);
fireEvent.mouseOver(sector, { clientX: 200, clientY: 200 });

const activeSector = container.querySelectorAll('.recharts-active-shape');
expect(activeSector).toHaveLength(1);
assertActiveShapeInteractions(container);
});

test('Renders customized active bar when activeBar is set to be a truthy boolean', () => {
Expand All @@ -306,12 +311,7 @@ describe('<RadialBarChart />', () => {
</RadialBarChart>,
);

const sectorNodes = container.querySelectorAll('.recharts-sector');
const [sector] = Array.from(sectorNodes);
fireEvent.mouseOver(sector, { clientX: 200, clientY: 200 });

const activeSector = container.querySelectorAll('.recharts-active-shape');
expect(activeSector).toHaveLength(1);
assertActiveShapeInteractions(container);
});

test('Does not render customized active bar when activeBar set to be a falsy boolean', () => {
Expand Down Expand Up @@ -356,13 +356,7 @@ describe('<RadialBarChart />', () => {
</RadialBarChart>,
);

const sectorNodes = container.querySelectorAll('.recharts-sector');

const [sector] = Array.from(sectorNodes);
fireEvent.mouseOver(sector, { clientX: 200, clientY: 200 });

const activeSector = container.querySelectorAll('.recharts-active-shape');
expect(activeSector).toHaveLength(1);
assertActiveShapeInteractions(container);
});

describe('RadialBarChart layout context', () => {
Expand Down

0 comments on commit 10ede6f

Please sign in to comment.