Skip to content

Commit

Permalink
Add scaling toggle prop to funnel charts
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelnesen committed Dec 9, 2024
1 parent b546085 commit b98270e
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 6 deletions.
3 changes: 3 additions & 0 deletions packages/polaris-viz/src/components/FunnelChartNext/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,15 @@ export interface ChartProps {
tooltipLabels: FunnelChartNextProps['tooltipLabels'];
xAxisOptions: Required<XAxisOptions>;
yAxisOptions: Required<YAxisOptions>;
enableScaling: boolean;
}

export function Chart({
data,
tooltipLabels,
xAxisOptions,
yAxisOptions,
enableScaling,
}: ChartProps) {
const [tooltipIndex, setTooltipIndex] = useState<number | null>(null);
const {containerBounds} = useChartContext();
Expand Down Expand Up @@ -80,6 +82,7 @@ export function Chart({
const {getBarHeight, shouldApplyScaling} = useFunnelBarScaling({
yScale,
values: yValues,
enableScaling,
});

const labels = useMemo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export type FunnelChartNextProps = {
};
xAxisOptions?: Pick<XAxisOptions, 'hide'>;
yAxisOptions?: Pick<YAxisOptions, 'labelFormatter'>;
enableScaling?: boolean;
} & ChartProps;

export function FunnelChartNext(props: FunnelChartNextProps) {
Expand All @@ -35,6 +36,7 @@ export function FunnelChartNext(props: FunnelChartNextProps) {
theme = defaultTheme,
xAxisOptions,
yAxisOptions,
enableScaling = true,
id,
isAnimated,
state,
Expand Down Expand Up @@ -73,6 +75,7 @@ export function FunnelChartNext(props: FunnelChartNextProps) {
tooltipLabels={tooltipLabels}
xAxisOptions={xAxisOptionsForChart}
yAxisOptions={yAxisOptionsForChart}
enableScaling={enableScaling}
/>
)}
</ChartContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ Default.args = {
reached: 'Reached this step',
dropped: 'Dropped off',
},
enableScaling: true,
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {Meta} from '@storybook/react';
import {
CHART_STATE_CONTROL_ARGS,
CONTROLS_ARGS,
SCALE_CONTROL_ARGS,
THEME_CONTROL_ARGS,
X_AXIS_OPTIONS_ARGS,
Y_AXIS_OPTIONS_ARGS,
Expand All @@ -27,5 +28,6 @@ export const META: Meta = {
yAxisOptions: Y_AXIS_OPTIONS_ARGS,
theme: THEME_CONTROL_ARGS,
state: CHART_STATE_CONTROL_ARGS,
enableScaling: SCALE_CONTROL_ARGS,
},
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Fragment, useCallback} from 'react';
import {Fragment} from 'react';
import {scaleBand, scaleLinear} from 'd3-scale';
import type {
DataSeries,
Expand All @@ -8,7 +8,6 @@ import type {
import {useChartContext} from '@shopify/polaris-viz-core';

import {useFunnelBarScaling} from '../../hooks';
import {getFunnelBarHeight} from '../FunnelChartNext';
import {FunnelChartConnectorGradient} from '../shared/FunnelChartConnector';
import {FunnelChartConnector, FunnelChartSegment} from '../shared';
import {ChartElements} from '../ChartElements';
Expand All @@ -20,12 +19,13 @@ export interface ChartProps {
tooltipLabels: SparkFunnelChartProps['tooltipLabels'];
xAxisOptions: Required<XAxisOptions>;
yAxisOptions: Required<YAxisOptions>;
enableScaling: boolean;
}

const LINE_OFFSET = 1;
const GAP = 1;

export function Chart({data}: ChartProps) {
export function Chart({data, enableScaling}: ChartProps) {
const {containerBounds} = useChartContext();

const dataSeries = data[0].data;
Expand All @@ -46,6 +46,7 @@ export function Chart({data}: ChartProps) {
const {getBarHeight, shouldApplyScaling} = useFunnelBarScaling({
yScale,
values: yValues,
enableScaling,
});

const sectionWidth = xScale.bandwidth();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export type SparkFunnelChartProps = {
};
xAxisOptions?: Pick<XAxisOptions, 'hide'>;
yAxisOptions?: Pick<YAxisOptions, 'labelFormatter'>;
enableScaling?: boolean;
} & ChartProps;

export function SparkFunnelChart(props: SparkFunnelChartProps) {
Expand All @@ -41,6 +42,7 @@ export function SparkFunnelChart(props: SparkFunnelChartProps) {
errorText,
onError,
tooltipLabels,
enableScaling = true,
} = {
...DEFAULT_CHART_PROPS,
...props,
Expand Down Expand Up @@ -74,6 +76,7 @@ export function SparkFunnelChart(props: SparkFunnelChartProps) {
xAxisOptions={xAxisOptionsForChart}
yAxisOptions={yAxisOptionsForChart}
tooltipLabels={tooltipLabels}
enableScaling={enableScaling}
/>
)}
</ChartContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ export const Default: Story<SparkFunnelChartProps> = Template.bind({});

Default.args = {
data: DEFAULT_DATA,
enableScaling: true,
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {Meta} from '@storybook/react';
import {
CHART_STATE_CONTROL_ARGS,
CONTROLS_ARGS,
SCALE_CONTROL_ARGS,
} from '../../../storybook/constants';
import {PageWithSizingInfo} from '../../Docs/stories';
import {SparkFunnelChart} from '../SparkFunnelChart';
Expand All @@ -21,5 +22,6 @@ export const META: Meta = {
},
argTypes: {
state: CHART_STATE_CONTROL_ARGS,
enableScaling: SCALE_CONTROL_ARGS,
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ describe('useFunnelBarScaling', () => {
const data = useFunnelBarScaling({
yScale: mockYScale,
values: [90, 100],
enableScaling: true,
});

return <span data-data={`${JSON.stringify(data)}`} />;
Expand All @@ -37,6 +38,7 @@ describe('useFunnelBarScaling', () => {
const data = useFunnelBarScaling({
yScale: mockYScale,
values: [5, 100],
enableScaling: true,
});

return <span data-data={`${JSON.stringify(data)}`} />;
Expand All @@ -49,11 +51,12 @@ describe('useFunnelBarScaling', () => {
});

describe('getBarHeight', () => {
it('returns original height when scaling not needed', () => {
it('returns original bar height when ratio is above scaling threshold', () => {
function TestComponent() {
const data = useFunnelBarScaling({
yScale: mockYScale,
values: [90, 100],
enableScaling: true,
});

const height = data.getBarHeight(90);
Expand All @@ -66,11 +69,30 @@ describe('useFunnelBarScaling', () => {
expect(data.height).toBe(mockYScale(90));
});

it('returns original height when scaling not enabled', () => {
function TestComponent() {
const data = useFunnelBarScaling({
yScale: mockYScale,
values: [5, 100],
enableScaling: false,
});

const height = data.getBarHeight(5);
return <span data-data={`${JSON.stringify({height})}`} />;
}

const result = mount(<TestComponent />);
const data = parseData(result);

expect(data.height).toBe(mockYScale(5));
});

it('returns scaled height when scaling needed', () => {
function TestComponent() {
const data = useFunnelBarScaling({
yScale: mockYScale,
values: [5, 100],
enableScaling: true,
});

const scaledHeight = data.getBarHeight(5);
Expand Down Expand Up @@ -103,6 +125,7 @@ describe('useFunnelBarScaling', () => {
const data = useFunnelBarScaling({
yScale: mockYScale,
values: [5, 100],
enableScaling: true,
});

const height = data.getBarHeight(100);
Expand Down
6 changes: 4 additions & 2 deletions packages/polaris-viz/src/hooks/useFunnelBarScaling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ export const MINIMUM_SEGMENT_HEIGHT_RATIO = 0.25;
interface UseFunnelBarScalingProps {
yScale: ScaleLinear<number, number>;
values: number[];
enableScaling: boolean;
}

export function useFunnelBarScaling({
yScale,
values,
enableScaling,
}: UseFunnelBarScalingProps) {
const tallestBarHeight = useMemo(
() => yScale(Math.max(...values)),
Expand All @@ -31,8 +33,8 @@ export function useFunnelBarScaling({
);

const shouldApplyScaling = useMemo(
() => smallestToTallestBarRatio <= SCALING_RATIO_THRESHOLD,
[smallestToTallestBarRatio],
() => smallestToTallestBarRatio <= SCALING_RATIO_THRESHOLD && enableScaling,
[smallestToTallestBarRatio, enableScaling],
);

const getBarHeight = useCallback(
Expand Down
8 changes: 8 additions & 0 deletions packages/polaris-viz/src/storybook/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ export const MAX_SERIES_ARGS = {
},
};

export const SCALE_CONTROL_ARGS = {
description:
'When enabled, small segments will be scaled up to be more visible relative to the largest segment while maintaining proportions.',
control: {
type: 'boolean',
},
};

export const DEFAULT_CHART_CONTEXT: ChartContextValues = {
shouldAnimate: false,
characterWidths,
Expand Down

0 comments on commit b98270e

Please sign in to comment.