Skip to content
This repository was archived by the owner on Jun 6, 2025. It is now read-only.

Commit 2fb7241

Browse files
committed
Add showTooltip prop
1 parent 0bfb45e commit 2fb7241

File tree

8 files changed

+131
-32
lines changed

8 files changed

+131
-32
lines changed

packages/polaris-viz/src/components/FunnelChartNext/Chart.tsx

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import type {ReactNode} from 'react';
22
import {Fragment, useMemo, useState} from 'react';
33
import {scaleBand, scaleLinear} from 'd3-scale';
4-
import type {DataSeries, LabelFormatter} from '@shopify/polaris-viz-core';
4+
import type {
5+
DataPoint,
6+
DataSeries,
7+
LabelFormatter,
8+
} from '@shopify/polaris-viz-core';
59
import {
610
uniqueId,
711
LinearGradientWithStops,
@@ -37,7 +41,8 @@ import type {FunnelChartNextProps} from './FunnelChartNext';
3741

3842
export interface ChartProps {
3943
data: DataSeries[];
40-
tooltipLabels: FunnelChartNextProps['tooltipLabels'];
44+
tooltipLabels?: FunnelChartNextProps['tooltipLabels'];
45+
showTooltip?: FunnelChartNextProps['showTooltip'];
4146
seriesNameFormatter: LabelFormatter;
4247
labelFormatter: LabelFormatter;
4348
percentageFormatter?: (value: number) => string;
@@ -47,6 +52,7 @@ export interface ChartProps {
4752
export function Chart({
4853
data,
4954
tooltipLabels,
55+
showTooltip = true,
5056
seriesNameFormatter,
5157
labelFormatter,
5258
percentageFormatter = (value: number) => {
@@ -178,8 +184,10 @@ export function Chart({
178184
barWidth={barWidth}
179185
index={index}
180186
isLast={isLast}
181-
onMouseEnter={(index) => setTooltipIndex(index)}
182-
onMouseLeave={() => setTooltipIndex(null)}
187+
onMouseEnter={(index) =>
188+
showTooltip && setTooltipIndex(index)
189+
}
190+
onMouseLeave={() => showTooltip && setTooltipIndex(null)}
183191
shouldApplyScaling={shouldApplyScaling}
184192
x={x}
185193
>
@@ -216,18 +224,13 @@ export function Chart({
216224
);
217225

218226
function getTooltipMarkup() {
219-
if (tooltipIndex == null) {
227+
if (!showTooltip || tooltipIndex == null || !dataSeries[tooltipIndex]) {
220228
return null;
221229
}
222230

223231
const activeDataSeries = dataSeries[tooltipIndex];
224-
225-
if (activeDataSeries == null) {
226-
return null;
227-
}
228-
229-
const xPosition = getXPosition();
230-
const yPosition = getYPosition();
232+
const xPosition = getXPosition(activeDataSeries);
233+
const yPosition = getYPosition(activeDataSeries);
231234

232235
return (
233236
<FunnelTooltip x={xPosition} y={yPosition}>
@@ -240,25 +243,25 @@ export function Chart({
240243
/>
241244
</FunnelTooltip>
242245
);
246+
}
243247

244-
function getXPosition() {
245-
if (tooltipIndex === 0) {
246-
return chartX + barWidth + TOOLTIP_HORIZONTAL_OFFSET;
247-
}
248-
249-
const xOffset = (barWidth - TOOLTIP_WIDTH) / 2;
250-
return chartX + (xScale(activeDataSeries.key.toString()) ?? 0) + xOffset;
248+
function getXPosition(activeDataSeries: DataPoint) {
249+
if (tooltipIndex === 0) {
250+
return chartX + barWidth + TOOLTIP_HORIZONTAL_OFFSET;
251251
}
252252

253-
function getYPosition() {
254-
const barHeight = getBarHeight(activeDataSeries.value ?? 0);
255-
const yPosition = chartY + drawableHeight - barHeight;
253+
const xOffset = (barWidth - TOOLTIP_WIDTH) / 2;
254+
return chartX + (xScale(activeDataSeries.key.toString()) ?? 0) + xOffset;
255+
}
256256

257-
if (tooltipIndex === 0) {
258-
return yPosition;
259-
}
257+
function getYPosition(activeDataSeries: DataPoint) {
258+
const barHeight = getBarHeight(activeDataSeries.value ?? 0);
259+
const yPosition = chartY + drawableHeight - barHeight;
260260

261-
return yPosition - TOOLTIP_HEIGHT;
261+
if (tooltipIndex === 0) {
262+
return yPosition;
262263
}
264+
265+
return yPosition - TOOLTIP_HEIGHT;
263266
}
264267
}

packages/polaris-viz/src/components/FunnelChartNext/FunnelChartNext.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,24 @@ import {ChartSkeleton} from '../';
1111

1212
import {Chart} from './Chart';
1313

14+
const DEFAULT_LABEL_FORMATTER: LabelFormatter = (value) => `${value}`;
15+
const DEFAULT_TOOLTIP_LABELS = {
16+
reached: 'Reached this step',
17+
dropped: 'Dropped off',
18+
} as const;
19+
1420
export type FunnelChartNextProps = {
15-
tooltipLabels: {
21+
tooltipLabels?: {
1622
reached: string;
1723
dropped: string;
1824
};
25+
showTooltip?: boolean;
1926
seriesNameFormatter?: LabelFormatter;
2027
labelFormatter?: LabelFormatter;
2128
renderScaleIconTooltipContent?: () => ReactNode;
2229
percentageFormatter?: (value: number) => string;
2330
} & ChartProps;
2431

25-
const DEFAULT_LABEL_FORMATTER: LabelFormatter = (value) => `${value}`;
26-
2732
export function FunnelChartNext(props: FunnelChartNextProps) {
2833
const {theme: defaultTheme} = useChartContext();
2934

@@ -34,7 +39,8 @@ export function FunnelChartNext(props: FunnelChartNextProps) {
3439
isAnimated,
3540
state,
3641
errorText,
37-
tooltipLabels,
42+
tooltipLabels = DEFAULT_TOOLTIP_LABELS,
43+
showTooltip = true,
3844
seriesNameFormatter = DEFAULT_LABEL_FORMATTER,
3945
labelFormatter = DEFAULT_LABEL_FORMATTER,
4046
percentageFormatter,
@@ -64,6 +70,7 @@ export function FunnelChartNext(props: FunnelChartNextProps) {
6470
<Chart
6571
data={data}
6672
tooltipLabels={tooltipLabels}
73+
showTooltip={showTooltip}
6774
seriesNameFormatter={seriesNameFormatter}
6875
labelFormatter={labelFormatter}
6976
percentageFormatter={percentageFormatter}

packages/polaris-viz/src/components/FunnelChartNext/components/Tooltip/Tooltip.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,24 @@ export function Tooltip({
6767
>
6868
{() => (
6969
<Fragment>
70-
<TooltipTitle theme={DEFAULT_THEME_NAME}>{point.key}</TooltipTitle>
70+
<TooltipTitle
71+
theme={DEFAULT_THEME_NAME}
72+
aria-label={`Step: ${point.key}`}
73+
>
74+
{point.key}
75+
</TooltipTitle>
7176
<div className={styles.Rows}>
7277
{data.map(({key, value, color, percent}, index) => {
78+
const ariaLabel = `${key}: ${value}, ${percentageFormatter(
79+
percent,
80+
)}`;
81+
7382
return (
74-
<div className={styles.Row} key={`row-${index}-${key}`}>
83+
<div
84+
className={styles.Row}
85+
key={`row-${index}-${key}`}
86+
aria-label={ariaLabel}
87+
>
7588
<div className={styles.Keys}>
7689
<SeriesIcon color={color!} shape="Bar" />
7790
<span>{key}</span>

packages/polaris-viz/src/components/FunnelChartNext/stories/Default.stories.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Default.args = {
2424
reached: 'Reached this step',
2525
dropped: 'Dropped off',
2626
},
27+
showTooltip: true,
2728
labelFormatter,
2829
percentageFormatter,
2930
renderScaleIconTooltipContent: () => (

packages/polaris-viz/src/components/FunnelChartNext/stories/meta.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import {
66
LABEL_FORMATTER_ARGS,
77
PERCENTAGE_FORMATTER_ARGS,
88
SERIES_NAME_FORMATTER_ARGS,
9+
SHOW_TOOLTIP_ARGS,
910
THEME_CONTROL_ARGS,
11+
FUNNEL_TOOLTIP_LABELS_ARGS,
1012
} from '../../../storybook/constants';
1113
import {PageWithSizingInfo} from '../../Docs/stories';
1214
import {FunnelChartNext} from '../FunnelChartNext';
@@ -27,6 +29,8 @@ export const META: Meta = {
2729
seriesNameFormatter: SERIES_NAME_FORMATTER_ARGS,
2830
labelFormatter: LABEL_FORMATTER_ARGS,
2931
percentageFormatter: PERCENTAGE_FORMATTER_ARGS,
32+
tooltipLabels: FUNNEL_TOOLTIP_LABELS_ARGS,
33+
showTooltip: SHOW_TOOLTIP_ARGS,
3034
theme: THEME_CONTROL_ARGS,
3135
state: CHART_STATE_CONTROL_ARGS,
3236
},

packages/polaris-viz/src/components/FunnelChartNext/tests/Chart.test.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,32 @@ describe('<Chart />', () => {
102102

103103
expect(chart).not.toContainReactComponent(FunnelTooltip);
104104
});
105+
106+
describe('showTooltip', () => {
107+
it('shows tooltip when showTooltip is true', () => {
108+
const chart = mount(
109+
<ChartContext.Provider value={mockContext}>
110+
<Chart {...defaultProps} showTooltip />
111+
</ChartContext.Provider>,
112+
);
113+
114+
const firstSegment = chart.find(FunnelChartSegment);
115+
firstSegment?.trigger('onMouseEnter', 0);
116+
117+
expect(chart).toContainReactComponent(FunnelTooltip);
118+
});
119+
120+
it('does not show tooltip when showTooltip is false', () => {
121+
const chart = mount(
122+
<ChartContext.Provider value={mockContext}>
123+
<Chart {...defaultProps} showTooltip={false} />
124+
</ChartContext.Provider>,
125+
);
126+
127+
const firstSegment = chart.find(FunnelChartSegment);
128+
firstSegment?.trigger('onMouseEnter', 0);
129+
130+
expect(chart).not.toContainReactComponent(FunnelTooltip);
131+
});
132+
});
105133
});

packages/polaris-viz/src/components/FunnelChartNext/tests/FunnelChartNext.test.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,5 +116,36 @@ describe('<FunnelChartNext />', () => {
116116
labelFormatter,
117117
});
118118
});
119+
120+
describe('showTooltip', () => {
121+
it('passes showTooltip prop to Chart', () => {
122+
const funnel = mount(
123+
<FunnelChartNext
124+
data={mockData}
125+
tooltipLabels={mockTooltipLabels}
126+
showTooltip={false}
127+
state={ChartState.Success}
128+
/>,
129+
);
130+
131+
expect(funnel).toContainReactComponent(Chart, {
132+
showTooltip: false,
133+
});
134+
});
135+
136+
it('defaults showTooltip to true when not provided', () => {
137+
const funnel = mount(
138+
<FunnelChartNext
139+
data={mockData}
140+
tooltipLabels={mockTooltipLabels}
141+
state={ChartState.Success}
142+
/>,
143+
);
144+
145+
expect(funnel).toContainReactComponent(Chart, {
146+
showTooltip: true,
147+
});
148+
});
149+
});
119150
});
120151
});

packages/polaris-viz/src/storybook/constants.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,18 @@ export const PERCENTAGE_FORMATTER_ARGS = {
151151
'A function that formats percentage values displayed in the chart.',
152152
};
153153

154+
export const FUNNEL_TOOLTIP_LABELS_ARGS = {
155+
description:
156+
'An object that defines the "reached" and "dropped" labels in the tooltip.',
157+
};
158+
159+
export const SHOW_TOOLTIP_ARGS = {
160+
description: 'Whether to show the tooltip or not.',
161+
control: {
162+
type: 'boolean',
163+
},
164+
};
165+
154166
export const DEFAULT_CHART_CONTEXT: ChartContextValues = {
155167
shouldAnimate: false,
156168
characterWidths,

0 commit comments

Comments
 (0)