Skip to content

Commit

Permalink
Merge pull request #1634 from Shopify/rita-morozova/add-group-sum-lab…
Browse files Browse the repository at this point in the history
…els-for-stacked-bar

Add group sum labels for the horizontal stacked bar
  • Loading branch information
rita-morozova authored Mar 4, 2024
2 parents 0291809 + 61df7a0 commit 1894d36
Show file tree
Hide file tree
Showing 20 changed files with 229 additions and 16 deletions.
7 changes: 7 additions & 0 deletions packages/polaris-viz-core/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ const DEFAULT_GRID_VERTICAL_OVERFLOW = true;
const DEFAULT_GRID_HORIZONTAL_MARGIN = 16;

const DEFAULT_X_AXIS_HIDE = false;
const DEFAULT_GROUP_LABEL_HIDE = false;

const DEFAULT_CROSSHAIR_WIDTH = 1;

Expand Down Expand Up @@ -212,6 +213,9 @@ export const DEFAULT_THEME: Theme = {
backgroundColor: variables.colorGray160,
labelColor: variables.colorGray30,
},
groupLabel: {
hide: DEFAULT_GROUP_LABEL_HIDE,
},
crossHair: {
color: variables.colorGray70,
width: DEFAULT_CROSSHAIR_WIDTH,
Expand Down Expand Up @@ -317,6 +321,9 @@ export const LIGHT_THEME: Theme = {
backgroundColor: variables.colorGray00,
labelColor: variables.colorGray100,
},
groupLabel: {
hide: DEFAULT_GROUP_LABEL_HIDE,
},
crossHair: {
color: variables.colorGray40,
width: DEFAULT_CROSSHAIR_WIDTH,
Expand Down
6 changes: 6 additions & 0 deletions packages/polaris-viz-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ export interface YAxisTheme {
backgroundColor: string;
}

export interface GroupLabelTheme {
hide: boolean;
}

export interface AnnotationsTheme {
backgroundColor: string;
textColor: string;
Expand Down Expand Up @@ -173,6 +177,7 @@ export interface PartialTheme {
grid?: Partial<GridTheme>;
xAxis?: Partial<XAxisTheme>;
yAxis?: Partial<YAxisTheme>;
groupLabel?: Partial<GroupLabelTheme>;
crossHair?: Partial<CrossHairTheme>;
legend?: Partial<LegendTheme>;
seriesColors?: Partial<SeriesColors>;
Expand All @@ -189,6 +194,7 @@ export interface Theme {
grid: GridTheme;
xAxis: XAxisTheme;
yAxis: YAxisTheme;
groupLabel: GroupLabelTheme;
line: LineTheme;
crossHair: CrossHairTheme;
legend: LegendTheme;
Expand Down
4 changes: 4 additions & 0 deletions packages/polaris-viz/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## Unreleased

### Added

- Added the group sum labels for the Horizontal Stacked Bar Chart.

### Fixed

- Fixed the positioning of the `<ZeroLine />` for the Stacked Horizontal Chart when all values are negative.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,25 @@ export {META as default} from './meta';
import type {BarChartProps} from '../../../components';

import {Template} from './data';
import {PolarisVizProvider} from '../../PolarisVizProvider';

export const HorizontalStacked: Story<BarChartProps> = Template.bind({});
export const HorizontalStacked: Story<BarChartProps> = (
args: BarChartProps,
) => {
return (
<PolarisVizProvider
themes={{
Default: {
groupLabel: {
hide: true,
},
},
}}
>
<Template {...args} />
</PolarisVizProvider>
);
};

HorizontalStacked.args = {
data: [
Expand Down Expand Up @@ -48,5 +65,5 @@ HorizontalStacked.args = {
},
],
type: 'stacked',
direction: 'horizontal'
direction: 'horizontal',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import type {Story} from '@storybook/react';

import type {BarChartProps} from '../../../components';

import {Template} from './data';

export {META as default} from './meta';

export const HorizontalStackedWithoutXAxisLabels: Story<BarChartProps> =
Template.bind({});

HorizontalStackedWithoutXAxisLabels.args = {
data: [
{
name: 'Breakfast',
data: [
{key: 'Monday', value: 1},
{key: 'Tuesday', value: -10},
{key: 'Wednesday', value: -7},
{key: 'Thursday', value: -0.12},
{key: 'Friday', value: 10},
{key: 'Saturday', value: 5},
{key: 'Sunday', value: 6},
],
},
{
name: 'Lunch',
data: [
{key: 'Monday', value: -10},
{key: 'Tuesday', value: 7},
{key: 'Wednesday', value: 12},
{key: 'Thursday', value: 4},
{key: 'Friday', value: -0.2},
{key: 'Saturday', value: -4},
{key: 'Sunday', value: -9},
],
},
{
name: 'Dinner',
data: [
{key: 'Monday', value: -1},
{key: 'Tuesday', value: 4},
{key: 'Wednesday', value: 2},
{key: 'Thursday', value: -2},
{key: 'Friday', value: 10},
{key: 'Saturday', value: 10},
{key: 'Sunday', value: 3},
],
},
],
type: 'stacked',
direction: 'horizontal',
xAxisOptions: {hide: true}
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ import {
} from '../../../constants';
import {useTheme, useWatchColorVisionEvents} from '../../../hooks';
import {getGradientDefId} from '../GradientDefs';
import {Label} from '../Label';
import {LabelWrapper} from '../LabelWrapper';
import {Bar} from '../Bar';

import {Label, Bar, LabelWrapper} from './components';
import styles from './HorizontalBars.scss';

const SERIES_DELAY = 150;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export {HorizontalBars} from './HorizontalBars';
export {Label} from './components';
export {Label} from '../Label';
export {LabelWrapper} from '../LabelWrapper';
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import type {DataSeries} from '@shopify/polaris-viz-core';
import type {HorizontalBarsProps} from '../HorizontalBars';
import {HorizontalBars} from '../HorizontalBars';
import {Bar} from '../../Bar';
import {Label, LabelWrapper} from '../components';
import {Label} from '../../Label';
import {LabelWrapper} from '../../LabelWrapper';
import {TrendIndicator} from '../../..';

jest.mock('d3-scale', () => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ export function HorizontalGroup({
name={name}
stackedValues={stackedValues}
xScale={xScale}
areAllNegative={areAllNegative}
labelFormatter={xAxisOptions.labelFormatter}
isSimple={isSimple}
/>
) : (
<HorizontalBars
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
import {Fragment, useMemo, useState} from 'react';
import type {ScaleLinear} from 'd3-scale';
import type {LabelFormatter} from '@shopify/polaris-viz-core';
import {
COLOR_VISION_SINGLE_ITEM,
BORDER_RADIUS,
useChartContext,
estimateStringWidth,
} from '@shopify/polaris-viz-core';

import {useWatchColorVisionEvents} from '../../../hooks';
import {useWatchColorVisionEvents, useTheme} from '../../../hooks';
import {getBarId} from '../../../utilities';
import {
HORIZONTAL_GROUP_LABEL_HEIGHT,
HORIZONTAL_BAR_LABEL_OFFSET,
NEGATIVE_ZERO_LINE_OFFSET,
} from '../../../constants';
import type {FormattedStackedSeries} from '../../../types';
import {getGradientDefId} from '..';
import {ZeroValueLine} from '../ZeroValueLine';
import {Label} from '../Label';
import {LabelWrapper} from '../LabelWrapper';

import {StackedBar} from './components';
import {useStackedGaps} from './hooks';
Expand All @@ -31,6 +36,9 @@ export interface HorizontalStackedBarsProps {
name: string;
stackedValues: FormattedStackedSeries[];
xScale: ScaleLinear<number, number>;
labelFormatter: LabelFormatter;
isSimple: boolean;
areAllNegative?: boolean;
}

function getBorderRadius({
Expand Down Expand Up @@ -63,9 +71,14 @@ export function HorizontalStackedBars({
name,
stackedValues,
xScale,
areAllNegative,
isSimple,
labelFormatter,
}: HorizontalStackedBarsProps) {
const {theme} = useChartContext();
const selectedTheme = useTheme();
const {theme, characterWidths} = useChartContext();
const [activeBarIndex, setActiveBarIndex] = useState(-1);
const hideGroupLabel = selectedTheme.groupLabel.hide;

useWatchColorVisionEvents({
type: COLOR_VISION_SINGLE_ITEM,
Expand Down Expand Up @@ -95,6 +108,32 @@ export function HorizontalStackedBars({

const gaps = useStackedGaps({stackedValues, groupIndex});

const groupSum = stackedValues[groupIndex].reduce((_, item) => {
if (item.data) {
return Object.values(item.data).reduce((sum, value) => sum + value, 0);
}
return 0;
}, 0);

const isNegative = groupSum && groupSum < 0;
const label = labelFormatter(groupSum);

const labelWidth = estimateStringWidth(`${label}`, characterWidths);

const minGroupStartPoint = stackedValues[groupIndex].reduce((min, item) => {
const start = item[0];
return start < min ? start : min;
}, Infinity);

const maxGroupEndPoint = stackedValues[groupIndex].reduce((max, item) => {
const end = item[1];
return end > max ? end : max;
}, -Infinity);

const groupLabelX = isNegative
? xScale(minGroupStartPoint) - labelWidth - HORIZONTAL_BAR_LABEL_OFFSET
: xScale(maxGroupEndPoint) + HORIZONTAL_BAR_LABEL_OFFSET;

return (
<g
style={{
Expand Down Expand Up @@ -124,7 +163,7 @@ export function HorizontalStackedBars({
<Fragment key={`stackedBar ${barId}`}>
{areAllValuesZero ? (
<ZeroValueLine
x={x - NEGATIVE_ZERO_LINE_OFFSET}
x={areAllNegative ? x - NEGATIVE_ZERO_LINE_OFFSET : x}
y={barHeight / 2}
direction="horizontal"
/>
Expand All @@ -147,6 +186,17 @@ export function HorizontalStackedBars({
</Fragment>
);
})}
{!isSimple && !hideGroupLabel && (
<LabelWrapper animationDelay={animationDelay} x={groupLabelX}>
<Label
barHeight={barHeight}
color={selectedTheme.xAxis.labelColor}
label={label}
labelWidth={labelWidth}
y={0}
/>
</LabelWrapper>
)}
</g>
);
}
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export {HorizontalStackedBars} from './HorizontalStackedBars';
export {LabelWrapper} from '../LabelWrapper';
export {Label} from '../Label';
Loading

0 comments on commit 1894d36

Please sign in to comment.