diff --git a/packages/polaris-viz/CHANGELOG.md b/packages/polaris-viz/CHANGELOG.md
index 4ce2a1c94..91e7aeaaf 100644
--- a/packages/polaris-viz/CHANGELOG.md
+++ b/packages/polaris-viz/CHANGELOG.md
@@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
-
+## Unreleased
+
+### Changed
+
+- Limit `` legends from taking up more than 50% of the chart width.
## [12.2.2] - 2024-04-01
diff --git a/packages/polaris-viz/src/components/DonutChart/Chart.tsx b/packages/polaris-viz/src/components/DonutChart/Chart.tsx
index 8936f62d5..71ae2731d 100644
--- a/packages/polaris-viz/src/components/DonutChart/Chart.tsx
+++ b/packages/polaris-viz/src/components/DonutChart/Chart.tsx
@@ -7,6 +7,7 @@ import {
useUniqueId,
ChartState,
useChartContext,
+ estimateStringWidth,
} from '@shopify/polaris-viz-core';
import type {
DataPoint,
@@ -17,7 +18,6 @@ import type {
} from '@shopify/polaris-viz-core';
import {getContainerAlignmentForLegend} from '../../utilities';
-import {estimateLegendItemWidth} from '../Legend';
import type {ComparisonMetricProps} from '../ComparisonMetric';
import {LegendContainer, useLegend} from '../../components/LegendContainer';
import {
@@ -40,7 +40,6 @@ import {InnerValue, LegendValues} from './components';
const ERROR_ANIMATION_PADDING = 40;
const FULL_CIRCLE = Math.PI * 2;
-const MAX_LEGEND_WIDTH_PERCENTAGE = 0.35;
const RADIUS_PADDING = 20;
export interface ChartProps {
@@ -98,28 +97,8 @@ export function Chart({
? 'vertical'
: 'horizontal';
- const longestLegendWidth = data.reduce((previous, current) => {
- const estimatedLegendWidth = estimateLegendItemWidth(
- showLegendValues === true
- ? `${current.name ?? ''} ${current.data[0].value}`
- : `${current.name ?? ''}`,
- characterWidths,
- );
-
- if (estimatedLegendWidth > previous) {
- return estimatedLegendWidth;
- }
-
- return previous;
- }, 0);
-
const maxLegendWidth =
- legendDirection === 'vertical'
- ? Math.max(
- longestLegendWidth,
- dimensions.width * MAX_LEGEND_WIDTH_PERCENTAGE,
- )
- : 0;
+ legendDirection === 'vertical' ? dimensions.width / 2 : 0;
const {height, width, legend, setLegendDimensions, isLegendMounted} =
useLegend({
@@ -131,6 +110,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,
);
@@ -147,7 +139,10 @@ export function Chart({
},
});
- if (!width || !height) return null;
+ if (!width || !height) {
+ return null;
+ }
+
const diameter = Math.min(height, width);
const radius = diameter / 2;
@@ -187,6 +182,7 @@ export function Chart({
data={data}
activeIndex={activeIndex}
labelFormatter={labelFormatter}
+ longestLegendValueWidth={longestLegendValueWidth}
getColorVisionStyles={getColorVisionStyles}
getColorVisionEventAttrs={getColorVisionEventAttrs}
dimensions={{...dimensions, x: 0, y: 0}}
diff --git a/packages/polaris-viz/src/components/DonutChart/components/LegendValues/LegendValues.scss b/packages/polaris-viz/src/components/DonutChart/components/LegendValues/LegendValues.scss
index 1768cf3c1..b435b0c60 100644
--- a/packages/polaris-viz/src/components/DonutChart/components/LegendValues/LegendValues.scss
+++ b/packages/polaris-viz/src/components/DonutChart/components/LegendValues/LegendValues.scss
@@ -2,4 +2,5 @@
width: 100%;
border-collapse: separate;
border-spacing: 0 10px;
+ table-layout: fixed;
}
diff --git a/packages/polaris-viz/src/components/DonutChart/components/LegendValues/LegendValues.tsx b/packages/polaris-viz/src/components/DonutChart/components/LegendValues/LegendValues.tsx
index 61f1fa0a8..c5c9a9ceb 100644
--- a/packages/polaris-viz/src/components/DonutChart/components/LegendValues/LegendValues.tsx
+++ b/packages/polaris-viz/src/components/DonutChart/components/LegendValues/LegendValues.tsx
@@ -24,6 +24,7 @@ interface LegendContentProps {
activeIndex: number;
dimensions: BoundingRect;
labelFormatter: LabelFormatter;
+ longestLegendValueWidth: number;
renderHiddenLegendLabel?: RenderHiddenLegendLabel;
getColorVisionStyles: ColorVisionInteractionMethods['getColorVisionStyles'];
getColorVisionEventAttrs: ColorVisionInteractionMethods['getColorVisionEventAttrs'];
@@ -33,6 +34,7 @@ export function LegendValues({
data: allData,
activeIndex,
labelFormatter,
+ longestLegendValueWidth,
renderHiddenLegendLabel = (count) => `+${count} more`,
getColorVisionStyles,
getColorVisionEventAttrs,
@@ -90,6 +92,7 @@ export function LegendValues({
value={value}
trend={trend}
index={index}
+ longestLegendValueWidth={longestLegendValueWidth}
maxTrendIndicatorWidth={maxTrendIndicatorWidth}
seriesColors={seriesColors}
onDimensionChange={(dimensions) => {
diff --git a/packages/polaris-viz/src/components/DonutChart/components/LegendValues/components/LegendValueItem/LegendValueItem.scss b/packages/polaris-viz/src/components/DonutChart/components/LegendValues/components/LegendValueItem/LegendValueItem.scss
index 2b4a4aa20..3788ae1d7 100644
--- a/packages/polaris-viz/src/components/DonutChart/components/LegendValues/components/LegendValueItem/LegendValueItem.scss
+++ b/packages/polaris-viz/src/components/DonutChart/components/LegendValues/components/LegendValueItem/LegendValueItem.scss
@@ -4,13 +4,10 @@
.Name {
overflow: hidden;
- text-wrap: nowrap;
+ white-space: nowrap;
text-overflow: ellipsis;
padding-left: 4px;
-}
-
-.TableSpacer {
- padding-left: 30px;
+ padding-right: 20px;
}
.alignLeft {
diff --git a/packages/polaris-viz/src/components/DonutChart/components/LegendValues/components/LegendValueItem/LegendValueItem.tsx b/packages/polaris-viz/src/components/DonutChart/components/LegendValues/components/LegendValueItem/LegendValueItem.tsx
index bb7420034..102b68767 100644
--- a/packages/polaris-viz/src/components/DonutChart/components/LegendValues/components/LegendValueItem/LegendValueItem.tsx
+++ b/packages/polaris-viz/src/components/DonutChart/components/LegendValues/components/LegendValueItem/LegendValueItem.tsx
@@ -21,6 +21,7 @@ interface Props {
value?: string;
trend?: MetaDataTrendIndicator;
labelFormatter: LabelFormatter;
+ longestLegendValueWidth: number;
seriesColors: Color[];
maxTrendIndicatorWidth: number;
onDimensionChange: (dimensions: Dimensions) => void;
@@ -33,6 +34,7 @@ export function LegendValueItem({
value,
index,
labelFormatter,
+ longestLegendValueWidth,
trend,
seriesColors,
maxTrendIndicatorWidth,
@@ -73,13 +75,12 @@ export function LegendValueItem({
style={{
color: selectedTheme.legend.labelColor,
}}
+ title={name}
>
{name}
-
|
-
-
+ |
|
-
- {trend && valueExists && }
- |
+ {trend && valueExists && (
+
+
+
+
+ |
+ )}
);
}
diff --git a/packages/polaris-viz/src/components/DonutChart/stories/DonutChart.chromatic.stories.tsx b/packages/polaris-viz/src/components/DonutChart/stories/DonutChart.chromatic.stories.tsx
new file mode 100644
index 000000000..eb6cf30f3
--- /dev/null
+++ b/packages/polaris-viz/src/components/DonutChart/stories/DonutChart.chromatic.stories.tsx
@@ -0,0 +1,112 @@
+import {storiesOf} from '@storybook/react';
+import type {PropCombinations} from '../../../chromatic/types';
+
+import {
+ addWithPropsCombinations,
+ renderCombinationSections,
+} from '../../../chromatic';
+import {DonutChart} from '../';
+import type {DonutChartProps} from '../DonutChart';
+import {DEFAULT_DATA} from './data';
+
+const stories = storiesOf('Chromatic/Components', module).addParameters({
+ docs: {page: null},
+ chromatic: {disableSnapshot: false},
+});
+
+const DEFAULT_PROPS: PropCombinations = {
+ data: [DEFAULT_DATA],
+ comparisonMetric: [
+ {
+ metric: '6%',
+ trend: 'positive',
+ accessibilityLabel: 'trending up 6%',
+ },
+ ],
+ legendPosition: ['left'],
+ isAnimated: [false],
+};
+
+const CHART_SIZE = {style: {width: 500, height: 300}};
+
+const combinations = renderCombinationSections([
+ [
+ 'Data',
+ addWithPropsCombinations(
+ DonutChart,
+ {
+ ...DEFAULT_PROPS,
+ },
+ CHART_SIZE,
+ ),
+ ],
+ [
+ 'Legend Position',
+ addWithPropsCombinations(
+ DonutChart,
+ {
+ ...DEFAULT_PROPS,
+ legendPosition: [
+ 'top-left',
+ 'top-right',
+ 'bottom-left',
+ 'bottom-right',
+ 'top',
+ 'right',
+ 'bottom',
+ 'left',
+ ],
+ },
+ CHART_SIZE,
+ ),
+ ],
+ [
+ 'Truncated Legends',
+ addWithPropsCombinations(
+ DonutChart,
+ {
+ ...DEFAULT_PROPS,
+ 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',
+ },
+ },
+ },
+ ],
+ ],
+ legendPosition: ['left', 'right'],
+ showLegendValues: [true, false],
+ },
+ CHART_SIZE,
+ ),
+ ],
+]);
+
+stories.add('DonutChart', combinations);
diff --git a/packages/polaris-viz/src/components/DonutChart/stories/TruncatedLegends.stories.tsx b/packages/polaris-viz/src/components/DonutChart/stories/TruncatedLegends.stories.tsx
new file mode 100644
index 000000000..a6d6390e6
--- /dev/null
+++ b/packages/polaris-viz/src/components/DonutChart/stories/TruncatedLegends.stories.tsx
@@ -0,0 +1,51 @@
+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 = Template.bind({});
+
+TruncatedLegends.args = {
+ ...DEFAULT_PROPS,
+ showLegendValues: true,
+ legendPosition: 'right',
+ legendFullWidth: false,
+ labelFormatter: (value) => `$${value}`,
+ isAnimated: false,
+ 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',
+ },
+ },
+ },
+ ],
+};
diff --git a/packages/polaris-viz/src/components/Legend/components/LegendItem/LegendItem.tsx b/packages/polaris-viz/src/components/Legend/components/LegendItem/LegendItem.tsx
index f42b282f1..df1766737 100644
--- a/packages/polaris-viz/src/components/Legend/components/LegendItem/LegendItem.tsx
+++ b/packages/polaris-viz/src/components/Legend/components/LegendItem/LegendItem.tsx
@@ -93,12 +93,13 @@ export function LegendItem({
paddingRight: LEGEND_ITEM_RIGHT_PADDING,
gap: LEGEND_ITEM_GAP,
// if there is overflow, add a max width and truncate with ellipsis
- maxWidth: truncate ? minWidth : undefined,
+ maxWidth: truncate ? minWidth : '100%',
// if the item width is less than the minWidth, don't set a min width
minWidth: width < minWidth ? undefined : minWidth,
}}
className={style.Legend}
ref={ref}
+ title={name}
>
{renderSeriesIcon == null ? (