Skip to content

Commit

Permalink
Limit Donut legend to 50% of chart width
Browse files Browse the repository at this point in the history
  • Loading branch information
envex committed Apr 2, 2024
1 parent 9acf2ed commit bc5ba5c
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 22 deletions.
33 changes: 24 additions & 9 deletions packages/polaris-viz/src/components/DonutChart/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
useUniqueId,
ChartState,
useChartContext,
estimateStringWidth,
} from '@shopify/polaris-viz-core';
import type {
DataPoint,
Expand Down Expand Up @@ -40,7 +41,7 @@ import {InnerValue, LegendValues} from './components';

const ERROR_ANIMATION_PADDING = 40;
const FULL_CIRCLE = Math.PI * 2;
const MAX_LEGEND_WIDTH_PERCENTAGE = 0.35;
const MAX_LEGEND_WIDTH_PERCENTAGE = 0.5;
const RADIUS_PADDING = 20;

export interface ChartProps {
Expand Down Expand Up @@ -113,13 +114,10 @@ export function Chart({
return previous;
}, 0);

const maxLegendWidth =
legendDirection === 'vertical'
? Math.max(
longestLegendWidth,
dimensions.width * MAX_LEGEND_WIDTH_PERCENTAGE,
)
: 0;
const maxLegendWidth = Math.min(
longestLegendWidth,
dimensions.width * MAX_LEGEND_WIDTH_PERCENTAGE,
);

const {height, width, legend, setLegendDimensions, isLegendMounted} =
useLegend({
Expand All @@ -131,6 +129,19 @@ export function Chart({
maxWidth: maxLegendWidth,
});

const longestLegendValueWidth = legend.reduce((previous, current) => {
const estimatedLegendWidth = estimateStringWidth(
`${labelFormatter(`${current.value || ''}`)}`,
characterWidths,
);

if (estimatedLegendWidth > previous) {
return estimatedLegendWidth;
}

return previous;
}, 0);

const shouldUseColorVisionEvents = Boolean(
width && height && isLegendMounted,
);
Expand All @@ -147,7 +158,10 @@ export function Chart({
},
});

if (!width || !height) return null;
if (!width || !height) {
return null;
}

const diameter = Math.min(height, width);
const radius = diameter / 2;

Expand Down Expand Up @@ -187,6 +201,7 @@ export function Chart({
data={data}
activeIndex={activeIndex}
labelFormatter={labelFormatter}
longestLegendValueWidth={longestLegendValueWidth}
getColorVisionStyles={getColorVisionStyles}
getColorVisionEventAttrs={getColorVisionEventAttrs}
dimensions={{...dimensions, x: 0, y: 0}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
width: 100%;
border-collapse: separate;
border-spacing: 0 10px;
table-layout: fixed;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface LegendContentProps {
activeIndex: number;
dimensions: BoundingRect;
labelFormatter: LabelFormatter;
longestLegendValueWidth: number;
renderHiddenLegendLabel?: RenderHiddenLegendLabel;
getColorVisionStyles: ColorVisionInteractionMethods['getColorVisionStyles'];
getColorVisionEventAttrs: ColorVisionInteractionMethods['getColorVisionEventAttrs'];
Expand All @@ -33,6 +34,7 @@ export function LegendValues({
data: allData,
activeIndex,
labelFormatter,
longestLegendValueWidth,
renderHiddenLegendLabel = (count) => `+${count} more`,
getColorVisionStyles,
getColorVisionEventAttrs,
Expand Down Expand Up @@ -90,6 +92,7 @@ export function LegendValues({
value={value}
trend={trend}
index={index}
longestLegendValueWidth={longestLegendValueWidth}
maxTrendIndicatorWidth={maxTrendIndicatorWidth}
seriesColors={seriesColors}
onDimensionChange={(dimensions) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
text-wrap: nowrap;
text-overflow: ellipsis;
padding-left: 4px;
}

.TableSpacer {
padding-left: 30px;
padding-right: 20px;
}

.alignLeft {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ interface Props {
value?: string;
trend?: MetaDataTrendIndicator;
labelFormatter: LabelFormatter;
longestLegendValueWidth: number;
seriesColors: Color[];
maxTrendIndicatorWidth: number;
onDimensionChange: (dimensions: Dimensions) => void;
Expand All @@ -33,6 +34,7 @@ export function LegendValueItem({
value,
index,
labelFormatter,
longestLegendValueWidth,
trend,
seriesColors,
maxTrendIndicatorWidth,
Expand Down Expand Up @@ -73,13 +75,12 @@ export function LegendValueItem({
style={{
color: selectedTheme.legend.labelColor,
}}
title={name}
>
<span>{name}</span>
</td>

<td className={styles.TableSpacer} />

<td className={styles.alignRight}>
<td className={styles.alignRight} width={longestLegendValueWidth}>
<span
style={{
color: selectedTheme.legend.labelColor,
Expand All @@ -89,12 +90,16 @@ export function LegendValueItem({
</span>
</td>

<td
className={styles.alignLeft}
style={{minWidth: maxTrendIndicatorWidth, paddingLeft: '4px'}}
>
<span>{trend && valueExists && <TrendIndicator {...trend} />}</span>
</td>
{trend && valueExists && (
<td
className={styles.alignLeft}
style={{minWidth: maxTrendIndicatorWidth, paddingLeft: '4px'}}
>
<span>
<TrendIndicator {...trend} />
</span>
</td>
)}
</tr>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type {Story} from '@storybook/react';

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

import type {DonutChartProps} from '../../DonutChart';

import {DEFAULT_PROPS, Template} from './data';

export const TruncatedLegends: Story<DonutChartProps> = Template.bind({});

TruncatedLegends.args = {
...DEFAULT_PROPS,
showLegendValues: true,
legendPosition: 'right',
legendFullWidth: false,
labelFormatter: (value) => `$${value}`,
data: [
{
name: 'This is a long name that will get truncated',
data: [{key: 'april - march', value: 50000}],
metadata: {
trend: {
value: '5%',
},
},
},
{
name: 'This is another long name that will get truncated',
data: [{key: 'april - march', value: 250000}],
metadata: {
trend: {
value: '50%',
direction: 'downward',
trend: 'negative',
},
},
},
{
name: 'This is the last long name that will get truncated',
data: [{key: 'april - march', value: 10000}],
metadata: {
trend: {
value: '100%',
direction: 'upward',
trend: 'positive',
},
},
},
],
};

0 comments on commit bc5ba5c

Please sign in to comment.