From 8d723c57ee31b5fc5b7e275ba330de2b26846b53 Mon Sep 17 00:00:00 2001 From: Kumar Kshitij Date: Fri, 16 Jun 2023 18:04:51 +0530 Subject: [PATCH 1/5] set minimum width for cartesian chart --- .../__snapshots__/AreaChart.test.tsx.snap | 39 ++++++++++ .../CommonComponents/CartesianChart.base.tsx | 58 +++++++++++--- .../CommonComponents/CartesianChart.styles.ts | 3 + .../CommonComponents/CartesianChart.types.ts | 5 ++ .../GroupedVerticalBarChart.test.tsx.snap | 27 +++++++ .../__snapshots__/HeatMapChart.test.tsx.snap | 18 +++++ .../HorizontalBarChartWithAxis.test.tsx.snap | 25 +++++-- .../__snapshots__/LineChart.test.tsx.snap | 33 ++++++++ .../VerticalBarChart.test.tsx.snap | 50 ++++++++++--- .../VerticalStackedBarChart.test.tsx.snap | 64 ++++++++++++---- .../react-charting/src/utilities/utilities.ts | 75 +++++++++++-------- 11 files changed, 327 insertions(+), 70 deletions(-) diff --git a/packages/react-charting/src/components/AreaChart/__snapshots__/AreaChart.test.tsx.snap b/packages/react-charting/src/components/AreaChart/__snapshots__/AreaChart.test.tsx.snap index 76fa2e8866ff2..6a7b5c01549c0 100644 --- a/packages/react-charting/src/components/AreaChart/__snapshots__/AreaChart.test.tsx.snap +++ b/packages/react-charting/src/components/AreaChart/__snapshots__/AreaChart.test.tsx.snap @@ -26,6 +26,9 @@ exports[`AreaChart - mouse events Should render callout correctly on mouseover 1 &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone6" onFocus={[Function]} onKeyDown={[Function]} @@ -565,6 +568,9 @@ exports[`AreaChart - mouse events Should render customized callout on mouseover &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone6" onFocus={[Function]} onKeyDown={[Function]} @@ -1001,6 +1007,9 @@ exports[`AreaChart - mouse events Should render customized callout per stack on &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone6" onFocus={[Function]} onKeyDown={[Function]} @@ -1437,6 +1446,9 @@ exports[`AreaChart snapShot testing Should not render circles when optimizeLarge &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone77" onFocus={[Function]} onKeyDown={[Function]} @@ -1751,6 +1763,9 @@ exports[`AreaChart snapShot testing Should render with default colors when line &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone69" onFocus={[Function]} onKeyDown={[Function]} @@ -2102,6 +2117,9 @@ exports[`AreaChart snapShot testing renders Areachart correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone6" onFocus={[Function]} onKeyDown={[Function]} @@ -2453,6 +2471,9 @@ exports[`AreaChart snapShot testing renders Areachart with single point correctl &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone61" onFocus={[Function]} onKeyDown={[Function]} @@ -2791,6 +2812,9 @@ exports[`AreaChart snapShot testing renders enabledLegendsWrapLines correctly 1` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone29" onFocus={[Function]} onKeyDown={[Function]} @@ -3122,6 +3146,9 @@ exports[`AreaChart snapShot testing renders hideLegend hhh correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone14" onFocus={[Function]} onKeyDown={[Function]} @@ -3313,6 +3340,9 @@ exports[`AreaChart snapShot testing renders hideTooltip correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone21" onFocus={[Function]} onKeyDown={[Function]} @@ -3664,6 +3694,9 @@ exports[`AreaChart snapShot testing renders showXAxisLablesTooltip correctly 1`] &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone37" onFocus={[Function]} onKeyDown={[Function]} @@ -4015,6 +4048,9 @@ exports[`AreaChart snapShot testing renders wrapXAxisLables correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone45" onFocus={[Function]} onKeyDown={[Function]} @@ -4366,6 +4402,9 @@ exports[`AreaChart snapShot testing renders yAxisTickFormat correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone53" onFocus={[Function]} onKeyDown={[Function]} diff --git a/packages/react-charting/src/components/CommonComponents/CartesianChart.base.tsx b/packages/react-charting/src/components/CommonComponents/CartesianChart.base.tsx index 55381a5f1c281..ba20ba02283c4 100644 --- a/packages/react-charting/src/components/CommonComponents/CartesianChart.base.tsx +++ b/packages/react-charting/src/components/CommonComponents/CartesianChart.base.tsx @@ -8,6 +8,7 @@ import { ICartesianChartStyleProps, IModifiedCartesianChartProps, IYValueHover, + IHorizontalBarChartWithAxisDataPoint, } from '../../index'; import { ChartHoverCard, @@ -28,7 +29,7 @@ import { rotateXAxisLabels, Points, pointTypes, - calculateLongestYAxisLabel, + calculateLongestLabelWidth, createYAxisLabels, ChartTypes, } from '../../utilities/index'; @@ -73,6 +74,7 @@ export class CartesianChartBase extends React.Component point.y), + `.${this._classNames.yAxis} text`, + ); if (this.state.startFromX !== maxYAxisLabelLength) { this.setState({ startFromX: maxYAxisLabelLength, @@ -166,7 +171,10 @@ export class CartesianChartBase extends React.Component point.y), + `.${this._classNames.yAxis} text`, + ); if (this.state.startFromX !== maxYAxisLabelLength) { this.setState({ startFromX: maxYAxisLabelLength, @@ -257,27 +265,34 @@ export class CartesianChartBase extends React.Component (this.chartContainer = rootElem)} onMouseLeave={this._onChartLeave} > - + legendContainerHeight ? container.getBoundingClientRect().height @@ -682,4 +697,27 @@ export class CartesianChartBase extends React.Component { this.props.onChartMouseLeave && this.props.onChartMouseLeave(); }; + + /* + TODO: + 1. Use reduced width for rotated and wrapped x-axis labels + 2. Check margins when x-axis labels don't start from the leftmost end + */ + private _calculateChartMinWidth = (): number => { + // TODO: Include label rotation and wrapping in calculation. labels + const maxLabelWidth = + Math.ceil(calculateLongestLabelWidth(this._tickValues, `.${this._classNames.xAxis} text`)) + 10; + let minChartWidth = this.margins.left! + this.margins.right! + maxLabelWidth * (this._tickValues.length - 1); + + if ( + [ChartTypes.GroupedVerticalBarChart, ChartTypes.VerticalBarChart, ChartTypes.VerticalStackedBarChart].includes( + this.props.chartType, + ) + ) { + const maxDomainMargin = 8 + 12; // MIN_DOMAIN_MARGIN + maxBarWidth / 2 + minChartWidth += maxDomainMargin * 2; + } + + return minChartWidth; + }; } diff --git a/packages/react-charting/src/components/CommonComponents/CartesianChart.styles.ts b/packages/react-charting/src/components/CommonComponents/CartesianChart.styles.ts index 4ceebdfbc4c06..783b67fb24f27 100644 --- a/packages/react-charting/src/components/CommonComponents/CartesianChart.styles.ts +++ b/packages/react-charting/src/components/CommonComponents/CartesianChart.styles.ts @@ -19,6 +19,9 @@ export const getStyles = (props: ICartesianChartStyleProps): ICartesianChartStyl }, className, ], + chartWrapper: { + overflow: 'auto', + }, xAxis: { selectors: { text: [ diff --git a/packages/react-charting/src/components/CommonComponents/CartesianChart.types.ts b/packages/react-charting/src/components/CommonComponents/CartesianChart.types.ts index b16ea1c54549a..62e3f041a68c6 100644 --- a/packages/react-charting/src/components/CommonComponents/CartesianChart.types.ts +++ b/packages/react-charting/src/components/CommonComponents/CartesianChart.types.ts @@ -146,6 +146,11 @@ export interface ICartesianChartStyles { * styles for the shape object in the callout */ shapeStyles?: IStyle; + + /** + * Styles for the chart wrapper div + */ + chartWrapper?: IStyle; } export interface ICartesianChartProps { diff --git a/packages/react-charting/src/components/GroupedVerticalBarChart/__snapshots__/GroupedVerticalBarChart.test.tsx.snap b/packages/react-charting/src/components/GroupedVerticalBarChart/__snapshots__/GroupedVerticalBarChart.test.tsx.snap index 8d0231cb09d05..f4c7cddb6106c 100644 --- a/packages/react-charting/src/components/GroupedVerticalBarChart/__snapshots__/GroupedVerticalBarChart.test.tsx.snap +++ b/packages/react-charting/src/components/GroupedVerticalBarChart/__snapshots__/GroupedVerticalBarChart.test.tsx.snap @@ -26,6 +26,9 @@ exports[`GroupedVerticalBarChart - mouse events Should render callout correctly &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone3" onFocus={[Function]} onKeyDown={[Function]} @@ -775,6 +778,9 @@ exports[`GroupedVerticalBarChart - mouse events Should render customized callout &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone3" onFocus={[Function]} onKeyDown={[Function]} @@ -1444,6 +1450,9 @@ exports[`GroupedVerticalBarChart snapShot testing renders GroupedVerticalBarChar &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone3" onFocus={[Function]} onKeyDown={[Function]} @@ -2025,6 +2034,9 @@ exports[`GroupedVerticalBarChart snapShot testing renders enabledLegendsWrapLine &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone17" onFocus={[Function]} onKeyDown={[Function]} @@ -2586,6 +2598,9 @@ exports[`GroupedVerticalBarChart snapShot testing renders hideLegend correctly 1 &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone8" onFocus={[Function]} onKeyDown={[Function]} @@ -2827,6 +2842,9 @@ exports[`GroupedVerticalBarChart snapShot testing renders hideTooltip correctly &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone12" onFocus={[Function]} onKeyDown={[Function]} @@ -3408,6 +3426,9 @@ exports[`GroupedVerticalBarChart snapShot testing renders showXAxisLablesTooltip &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone22" onFocus={[Function]} onKeyDown={[Function]} @@ -3989,6 +4010,9 @@ exports[`GroupedVerticalBarChart snapShot testing renders wrapXAxisLables correc &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone27" onFocus={[Function]} onKeyDown={[Function]} @@ -4570,6 +4594,9 @@ exports[`GroupedVerticalBarChart snapShot testing renders yAxisTickFormat correc &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone32" onFocus={[Function]} onKeyDown={[Function]} diff --git a/packages/react-charting/src/components/HeatMapChart/__snapshots__/HeatMapChart.test.tsx.snap b/packages/react-charting/src/components/HeatMapChart/__snapshots__/HeatMapChart.test.tsx.snap index 1502dc4c76749..b7ccb5f99e720 100644 --- a/packages/react-charting/src/components/HeatMapChart/__snapshots__/HeatMapChart.test.tsx.snap +++ b/packages/react-charting/src/components/HeatMapChart/__snapshots__/HeatMapChart.test.tsx.snap @@ -26,6 +26,9 @@ exports[`HeatMapChart - mouse events Should render callout correctly on mouseove &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone1" onFocus={[Function]} onKeyDown={[Function]} @@ -580,6 +583,9 @@ exports[`HeatMapChart snapShot testing renders HeatMapChart correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone1" onFocus={[Function]} onKeyDown={[Function]} @@ -916,6 +922,9 @@ exports[`HeatMapChart snapShot testing renders corretly even when data is not pr &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone4" onFocus={[Function]} onKeyDown={[Function]} @@ -1342,6 +1351,9 @@ exports[`HeatMapChart snapShot testing renders hideLegend correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone7" onFocus={[Function]} onKeyDown={[Function]} @@ -1518,6 +1530,9 @@ exports[`HeatMapChart snapShot testing renders hideTooltip correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone9" onFocus={[Function]} onKeyDown={[Function]} @@ -1854,6 +1869,9 @@ exports[`HeatMapChart snapShot testing renders yAxisTickFormat correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone12" onFocus={[Function]} onKeyDown={[Function]} diff --git a/packages/react-charting/src/components/HorizontalBarChartWithAxis/__snapshots__/HorizontalBarChartWithAxis.test.tsx.snap b/packages/react-charting/src/components/HorizontalBarChartWithAxis/__snapshots__/HorizontalBarChartWithAxis.test.tsx.snap index 47c81b90f329c..7f1b701b55d65 100644 --- a/packages/react-charting/src/components/HorizontalBarChartWithAxis/__snapshots__/HorizontalBarChartWithAxis.test.tsx.snap +++ b/packages/react-charting/src/components/HorizontalBarChartWithAxis/__snapshots__/HorizontalBarChartWithAxis.test.tsx.snap @@ -26,6 +26,9 @@ exports[`HorizontalBarChartWithAxis - mouse events Should render callout correct &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone3" onFocus={[Function]} onKeyDown={[Function]} @@ -38,7 +41,7 @@ exports[`HorizontalBarChartWithAxis - mouse events Should render callout correct "display": "block", } } - width={0} + width={140} > @@ -136,7 +139,7 @@ exports[`HorizontalBarChartWithAxis - mouse events Should render callout correct onMouseLeave={[Function]} onMouseOver={[Function]} role="img" - width={-37.5} + width={50} x={40} y={106} /> @@ -157,7 +160,7 @@ exports[`HorizontalBarChartWithAxis - mouse events Should render callout correct onMouseLeave={[Function]} onMouseOver={[Function]} role="img" - width={-40} + width={80} x={40} y={192.7} /> @@ -178,7 +181,7 @@ exports[`HorizontalBarChartWithAxis - mouse events Should render callout correct onMouseLeave={[Function]} onMouseOver={[Function]} role="img" - width={-15} + width={20} x={40} y={233.5} /> @@ -1205,6 +1208,9 @@ exports[`HorizontalBarChartWithAxis snapShot testing renders HorizontalBarChartW &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone3" onFocus={[Function]} onKeyDown={[Function]} @@ -1765,6 +1771,9 @@ exports[`HorizontalBarChartWithAxis snapShot testing renders hideLegend correctl &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone8" onFocus={[Function]} onKeyDown={[Function]} @@ -1895,6 +1904,9 @@ exports[`HorizontalBarChartWithAxis snapShot testing renders showToolTipForYAxis &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone12" onFocus={[Function]} onKeyDown={[Function]} @@ -2443,6 +2455,9 @@ exports[`HorizontalBarChartWithAxis snapShot testing renders showYAxisLables cor &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone17" onFocus={[Function]} onKeyDown={[Function]} diff --git a/packages/react-charting/src/components/LineChart/__snapshots__/LineChart.test.tsx.snap b/packages/react-charting/src/components/LineChart/__snapshots__/LineChart.test.tsx.snap index 4afb2190e3cc4..0d62fa26cab2c 100644 --- a/packages/react-charting/src/components/LineChart/__snapshots__/LineChart.test.tsx.snap +++ b/packages/react-charting/src/components/LineChart/__snapshots__/LineChart.test.tsx.snap @@ -26,6 +26,9 @@ exports[`LineChart - mouse events Should render callout correctly on mouseover 1 &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone9" onFocus={[Function]} onKeyDown={[Function]} @@ -547,6 +550,9 @@ exports[`LineChart - mouse events Should render customized callout on mouseover &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone9" onFocus={[Function]} onKeyDown={[Function]} @@ -966,6 +972,9 @@ exports[`LineChart - mouse events Should render customized callout per stack on &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone9" onFocus={[Function]} onKeyDown={[Function]} @@ -1385,6 +1394,9 @@ exports[`LineChart snapShot testing Should render with default colors when line &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone85" onFocus={[Function]} onKeyDown={[Function]} @@ -1719,6 +1731,9 @@ exports[`LineChart snapShot testing renders LineChart correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone9" onFocus={[Function]} onKeyDown={[Function]} @@ -2053,6 +2068,9 @@ exports[`LineChart snapShot testing renders enabledLegendsWrapLines correctly 1` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone41" onFocus={[Function]} onKeyDown={[Function]} @@ -2367,6 +2385,9 @@ exports[`LineChart snapShot testing renders hideLegend correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone20" onFocus={[Function]} onKeyDown={[Function]} @@ -2541,6 +2562,9 @@ exports[`LineChart snapShot testing renders hideTooltip correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone30" onFocus={[Function]} onKeyDown={[Function]} @@ -2875,6 +2899,9 @@ exports[`LineChart snapShot testing renders showXAxisLablesTooltip correctly 1`] &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone52" onFocus={[Function]} onKeyDown={[Function]} @@ -3209,6 +3236,9 @@ exports[`LineChart snapShot testing renders wrapXAxisLables correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone63" onFocus={[Function]} onKeyDown={[Function]} @@ -3543,6 +3573,9 @@ exports[`LineChart snapShot testing renders yAxisTickFormat correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone74" onFocus={[Function]} onKeyDown={[Function]} diff --git a/packages/react-charting/src/components/VerticalBarChart/__snapshots__/VerticalBarChart.test.tsx.snap b/packages/react-charting/src/components/VerticalBarChart/__snapshots__/VerticalBarChart.test.tsx.snap index 50567ccc8a2a8..a24369690000d 100644 --- a/packages/react-charting/src/components/VerticalBarChart/__snapshots__/VerticalBarChart.test.tsx.snap +++ b/packages/react-charting/src/components/VerticalBarChart/__snapshots__/VerticalBarChart.test.tsx.snap @@ -26,6 +26,9 @@ exports[`VerticalBarChart - mouse events Should render callout correctly on mous &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone3" onFocus={[Function]} onKeyDown={[Function]} @@ -38,7 +41,7 @@ exports[`VerticalBarChart - mouse events Should render callout correctly on mous "display": "block", } } - width={0} + width={150} > 50.0k @@ -193,7 +196,7 @@ exports[`VerticalBarChart - mouse events Should render callout correctly on mous onMouseOver={[Function]} role="img" width={16} - x={-40.46153846153846} + x={103.76923076923076} y={122} /> 30.0k @@ -730,6 +733,9 @@ exports[`VerticalBarChart - mouse events Should render customized callout on mou &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone3" onFocus={[Function]} onKeyDown={[Function]} @@ -742,7 +748,7 @@ exports[`VerticalBarChart - mouse events Should render customized callout on mou "display": "block", } } - width={0} + width={150} > 50.0k @@ -897,7 +903,7 @@ exports[`VerticalBarChart - mouse events Should render customized callout on mou onMouseOver={[Function]} role="img" width={16} - x={-40.46153846153846} + x={103.76923076923076} y={122} /> 30.0k @@ -1353,6 +1359,9 @@ exports[`VerticalBarChart snapShot testing Should not render bar labels 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone37" onFocus={[Function]} onKeyDown={[Function]} @@ -1803,6 +1812,9 @@ exports[`VerticalBarChart snapShot testing renders VerticalBarChart correctly 1` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone3" onFocus={[Function]} onKeyDown={[Function]} @@ -2253,6 +2265,9 @@ exports[`VerticalBarChart snapShot testing renders enabledLegendsWrapLines corre &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone17" onFocus={[Function]} onKeyDown={[Function]} @@ -2683,6 +2698,9 @@ exports[`VerticalBarChart snapShot testing renders hideLegend correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone8" onFocus={[Function]} onKeyDown={[Function]} @@ -2793,6 +2811,9 @@ exports[`VerticalBarChart snapShot testing renders hideTooltip correctly 1`] = ` &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone12" onFocus={[Function]} onKeyDown={[Function]} @@ -3243,6 +3264,9 @@ exports[`VerticalBarChart snapShot testing renders showXAxisLablesTooltip correc &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone22" onFocus={[Function]} onKeyDown={[Function]} @@ -3693,6 +3717,9 @@ exports[`VerticalBarChart snapShot testing renders wrapXAxisLables correctly 1`] &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone27" onFocus={[Function]} onKeyDown={[Function]} @@ -4143,6 +4170,9 @@ exports[`VerticalBarChart snapShot testing renders yAxisTickFormat correctly 1`] &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone32" onFocus={[Function]} onKeyDown={[Function]} diff --git a/packages/react-charting/src/components/VerticalStackedBarChart/__snapshots__/VerticalStackedBarChart.test.tsx.snap b/packages/react-charting/src/components/VerticalStackedBarChart/__snapshots__/VerticalStackedBarChart.test.tsx.snap index c08589f1d6b27..5e2f4300aaa71 100644 --- a/packages/react-charting/src/components/VerticalStackedBarChart/__snapshots__/VerticalStackedBarChart.test.tsx.snap +++ b/packages/react-charting/src/components/VerticalStackedBarChart/__snapshots__/VerticalStackedBarChart.test.tsx.snap @@ -26,6 +26,9 @@ exports[`VerticalStackedBarChart - mouse events Should render callout correctly &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone3" onFocus={[Function]} onKeyDown={[Function]} @@ -38,7 +41,7 @@ exports[`VerticalStackedBarChart - mouse events Should render callout correctly "display": "block", } } - width={0} + width={140} > @@ -238,7 +241,7 @@ exports[`VerticalStackedBarChart - mouse events Should render callout correctly role="img" textAnchor="middle" transform="translate(0, 0)" - x={-36} + x={104} y={23.807692307692307} > 50 @@ -672,6 +675,9 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone3" onFocus={[Function]} onKeyDown={[Function]} @@ -684,7 +690,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout "display": "block", } } - width={0} + width={140} > @@ -884,7 +890,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout role="img" textAnchor="middle" transform="translate(0, 0)" - x={-36} + x={104} y={23.807692307692307} > 50 @@ -1236,6 +1242,9 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone3" onFocus={[Function]} onKeyDown={[Function]} @@ -1248,7 +1257,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout "display": "block", } } - width={0} + width={140} > @@ -1430,7 +1439,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout role="img" textAnchor="middle" transform="translate(0, 0)" - x={-36} + x={104} y={23.807692307692307} > 50 @@ -1446,7 +1455,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout strokeWidth={3} transform="translate(0, 0)" x1={56} - x2={-36} + x2={104} y1={201.4423076923077} y2={127.88461538461539} /> @@ -1463,7 +1472,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout visibility="visibility" /> { + const tickFormat = xAxis.tickFormat(); + return tickFormat ? tickFormat(val, idx) : multiFormat(val as Date); + }); + return { xScale: xAxisScale, tickValues }; } /** @@ -283,7 +289,8 @@ export function createStringXAxis( if (xAxisParams.xAxisElement) { d3Select(xAxisParams.xAxisElement).call(xAxis).selectAll('text').attr('aria-hidden', 'true'); } - return xAxisScale; + const tickValues = dataset.map(xAxis.tickFormat()!); + return { xScale: xAxisScale, tickValues }; } /** @@ -724,28 +731,34 @@ export function createYAxisLabels( } }); } + /** - * This function is calculating the length of longest Y axis label in px ,so that we are able to - * create the cartesian chart by shifting that many points to the right/left. - * @param points - * @returns + * Calculates the width of the longest axis label in pixels */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function calculateLongestYAxisLabel( - points: IHorizontalBarChartWithAxisDataPoint[], - yAxisElement: SVGElement, -): number { - let maxLabelLength = 0; - points.forEach((point: IHorizontalBarChartWithAxisDataPoint) => { - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - ctx!.font = window.getComputedStyle(yAxisElement, null).getPropertyValue('font-size'); - const wordLengthInPixel = ctx!.measureText(point.y as string).width; - maxLabelLength = Math.max(wordLengthInPixel, maxLabelLength); - }); +export const calculateLongestLabelWidth = (labels: (string | number)[], query: string = 'none'): number => { + let maxLabelWidth = 0; + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + + if (ctx) { + const axisText = document.querySelector(query); + if (axisText) { + const styles = window.getComputedStyle(axisText, null); + const fontWeight = styles.getPropertyValue('font-weight'); + const fontSize = styles.getPropertyValue('font-size'); + const fontFamily = styles.getPropertyValue('font-family'); + ctx.font = `${fontWeight} ${fontSize} ${fontFamily}`; + } else { + ctx.font = 'bold 10px "Segoe UI"'; + } - return maxLabelLength; -} + labels.forEach(label => { + maxLabelWidth = Math.max(ctx.measureText(label.toString()).width, maxLabelWidth); + }); + } + + return maxLabelWidth; +}; /** * This method displays a tooltip to the x axis lables(tick values) From 87c26cc63a31071d6b2d2cbee9078975c56479dd Mon Sep 17 00:00:00 2001 From: Kumar Kshitij Date: Sat, 17 Jun 2023 00:37:18 +0530 Subject: [PATCH 2/5] include label rotation and wrapping in calculations --- .../CommonComponents/CartesianChart.base.tsx | 50 +++++++++++++++---- .../VerticalBarChart.test.tsx.snap | 20 ++++---- .../VerticalStackedBarChart.test.tsx.snap | 28 +++++------ .../react-charting/src/utilities/utilities.ts | 2 +- 4 files changed, 64 insertions(+), 36 deletions(-) diff --git a/packages/react-charting/src/components/CommonComponents/CartesianChart.base.tsx b/packages/react-charting/src/components/CommonComponents/CartesianChart.base.tsx index ba20ba02283c4..5c7bce6a9ba0c 100644 --- a/packages/react-charting/src/components/CommonComponents/CartesianChart.base.tsx +++ b/packages/react-charting/src/components/CommonComponents/CartesianChart.base.tsx @@ -698,24 +698,52 @@ export class CartesianChartBase extends React.Component { - // TODO: Include label rotation and wrapping in calculation. labels - const maxLabelWidth = - Math.ceil(calculateLongestLabelWidth(this._tickValues, `.${this._classNames.xAxis} text`)) + 10; - let minChartWidth = this.margins.left! + this.margins.right! + maxLabelWidth * (this._tickValues.length - 1); + let labelWidth = 10; // label padding + // Case: rotated labels + if ( + !this.props.wrapXAxisLables && + this.props.rotateXAxisLables && + this.props.xAxisType! === XAxisTypes.StringAxis + ) { + const longestLabelWidth = calculateLongestLabelWidth(this._tickValues, `.${this._classNames.xAxis} text`); + labelWidth += Math.ceil(longestLabelWidth * Math.cos(Math.PI / 4)); + } + // Case: truncated labels + else if (this.props.showXAxisLablesTooltip) { + const tickValues = this._tickValues.map(val => { + const numChars = this.props.noOfCharsToTruncate || 4; + return val.toString().length > numChars ? `${val.toString().slice(0, numChars)}...` : val; + }); + + const longestLabelWidth = calculateLongestLabelWidth(tickValues, `.${this._classNames.xAxis} text`); + labelWidth += Math.ceil(longestLabelWidth); + } + // Case: wrapped labels + else if (this.props.wrapXAxisLables) { + const words: string[] = []; + this._tickValues.forEach((val: string) => { + words.push(...val.toString().split(/\s+/)); + }); + + const longestLabelWidth = calculateLongestLabelWidth(words, `.${this._classNames.xAxis} text`); + labelWidth += Math.max(Math.ceil(longestLabelWidth), 10); + } + // Default case + else { + const longestLabelWidth = calculateLongestLabelWidth(this._tickValues, `.${this._classNames.xAxis} text`); + labelWidth += Math.ceil(longestLabelWidth); + } + + let minChartWidth = this.margins.left! + this.margins.right! + labelWidth * (this._tickValues.length - 1); if ( [ChartTypes.GroupedVerticalBarChart, ChartTypes.VerticalBarChart, ChartTypes.VerticalStackedBarChart].includes( this.props.chartType, ) ) { - const maxDomainMargin = 8 + 12; // MIN_DOMAIN_MARGIN + maxBarWidth / 2 - minChartWidth += maxDomainMargin * 2; + const minDomainMargin = 8; + minChartWidth += minDomainMargin * 2; } return minChartWidth; diff --git a/packages/react-charting/src/components/VerticalBarChart/__snapshots__/VerticalBarChart.test.tsx.snap b/packages/react-charting/src/components/VerticalBarChart/__snapshots__/VerticalBarChart.test.tsx.snap index a24369690000d..83abb2dcdcc2a 100644 --- a/packages/react-charting/src/components/VerticalBarChart/__snapshots__/VerticalBarChart.test.tsx.snap +++ b/packages/react-charting/src/components/VerticalBarChart/__snapshots__/VerticalBarChart.test.tsx.snap @@ -41,7 +41,7 @@ exports[`VerticalBarChart - mouse events Should render callout correctly on mous "display": "block", } } - width={150} + width={126} > 50.0k @@ -196,7 +196,7 @@ exports[`VerticalBarChart - mouse events Should render callout correctly on mous onMouseOver={[Function]} role="img" width={16} - x={103.76923076923076} + x={80.6923076923077} y={122} /> 30.0k @@ -748,7 +748,7 @@ exports[`VerticalBarChart - mouse events Should render customized callout on mou "display": "block", } } - width={150} + width={126} > 50.0k @@ -903,7 +903,7 @@ exports[`VerticalBarChart - mouse events Should render customized callout on mou onMouseOver={[Function]} role="img" width={16} - x={103.76923076923076} + x={80.6923076923077} y={122} /> 30.0k diff --git a/packages/react-charting/src/components/VerticalStackedBarChart/__snapshots__/VerticalStackedBarChart.test.tsx.snap b/packages/react-charting/src/components/VerticalStackedBarChart/__snapshots__/VerticalStackedBarChart.test.tsx.snap index 5e2f4300aaa71..360132334a360 100644 --- a/packages/react-charting/src/components/VerticalStackedBarChart/__snapshots__/VerticalStackedBarChart.test.tsx.snap +++ b/packages/react-charting/src/components/VerticalStackedBarChart/__snapshots__/VerticalStackedBarChart.test.tsx.snap @@ -41,7 +41,7 @@ exports[`VerticalStackedBarChart - mouse events Should render callout correctly "display": "block", } } - width={140} + width={116} > @@ -241,7 +241,7 @@ exports[`VerticalStackedBarChart - mouse events Should render callout correctly role="img" textAnchor="middle" transform="translate(0, 0)" - x={104} + x={80} y={23.807692307692307} > 50 @@ -690,7 +690,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout "display": "block", } } - width={140} + width={116} > @@ -890,7 +890,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout role="img" textAnchor="middle" transform="translate(0, 0)" - x={104} + x={80} y={23.807692307692307} > 50 @@ -1257,7 +1257,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout "display": "block", } } - width={140} + width={116} > @@ -1439,7 +1439,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout role="img" textAnchor="middle" transform="translate(0, 0)" - x={104} + x={80} y={23.807692307692307} > 50 @@ -1455,7 +1455,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout strokeWidth={3} transform="translate(0, 0)" x1={56} - x2={104} + x2={80} y1={201.4423076923077} y2={127.88461538461539} /> @@ -1472,7 +1472,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout visibility="visibility" /> { From 2a71248126fc7fbc8b8798fd6676bd084493a08e Mon Sep 17 00:00:00 2001 From: Kumar Kshitij Date: Sat, 17 Jun 2023 00:45:42 +0530 Subject: [PATCH 3/5] add change file --- ...eact-charting-1f77b865-250d-4cb3-bb5a-93fbdbf94a7c.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@fluentui-react-charting-1f77b865-250d-4cb3-bb5a-93fbdbf94a7c.json diff --git a/change/@fluentui-react-charting-1f77b865-250d-4cb3-bb5a-93fbdbf94a7c.json b/change/@fluentui-react-charting-1f77b865-250d-4cb3-bb5a-93fbdbf94a7c.json new file mode 100644 index 0000000000000..d9db3e25e03d5 --- /dev/null +++ b/change/@fluentui-react-charting-1f77b865-250d-4cb3-bb5a-93fbdbf94a7c.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Fix overlapping axis labels on smaller viewports", + "packageName": "@fluentui/react-charting", + "email": "kumarkshitij@microsoft.com", + "dependentChangeType": "patch" +} From ca9cc946ebb87491b281cd4fc6fccae3ae8dbe91 Mon Sep 17 00:00:00 2001 From: Kumar Kshitij Date: Mon, 19 Jun 2023 16:13:37 +0530 Subject: [PATCH 4/5] add prop to enable reflow --- .../CommonComponents/CartesianChart.base.tsx | 7 +++-- .../CommonComponents/CartesianChart.types.ts | 6 ++++ .../HorizontalBarChartWithAxis.test.tsx.snap | 10 +++---- .../components/LineChart/LineChart.base.tsx | 4 +++ .../VerticalBarChart.test.tsx.snap | 20 ++++++------- .../VerticalStackedBarChart.test.tsx.snap | 28 +++++++++---------- 6 files changed, 44 insertions(+), 31 deletions(-) diff --git a/packages/react-charting/src/components/CommonComponents/CartesianChart.base.tsx b/packages/react-charting/src/components/CommonComponents/CartesianChart.base.tsx index 5c7bce6a9ba0c..e3bb0550ee056 100644 --- a/packages/react-charting/src/components/CommonComponents/CartesianChart.base.tsx +++ b/packages/react-charting/src/components/CommonComponents/CartesianChart.base.tsx @@ -662,7 +662,9 @@ export class CartesianChartBase extends React.Component legendContainerHeight ? container.getBoundingClientRect().height @@ -699,7 +701,8 @@ export class CartesianChartBase extends React.Component { - let labelWidth = 10; // label padding + let labelWidth = 10; // Total padding on the left and right sides of the label + // Case: rotated labels if ( !this.props.wrapXAxisLables && diff --git a/packages/react-charting/src/components/CommonComponents/CartesianChart.types.ts b/packages/react-charting/src/components/CommonComponents/CartesianChart.types.ts index 62e3f041a68c6..982786f414379 100644 --- a/packages/react-charting/src/components/CommonComponents/CartesianChart.types.ts +++ b/packages/react-charting/src/components/CommonComponents/CartesianChart.types.ts @@ -374,6 +374,12 @@ export interface ICartesianChartProps { * props for the svg; use this to include aria-* or other attributes on the tag */ svgProps?: React.SVGProps; + + /** + * Prop to disable shrinking of the chart beyond a certain limit and enable scrolling when the chart overflows + * @default True for LineChart but False for other charts + */ + enableReflow?: boolean; } export interface IYValueHover { diff --git a/packages/react-charting/src/components/HorizontalBarChartWithAxis/__snapshots__/HorizontalBarChartWithAxis.test.tsx.snap b/packages/react-charting/src/components/HorizontalBarChartWithAxis/__snapshots__/HorizontalBarChartWithAxis.test.tsx.snap index 7f1b701b55d65..047636d3e3e73 100644 --- a/packages/react-charting/src/components/HorizontalBarChartWithAxis/__snapshots__/HorizontalBarChartWithAxis.test.tsx.snap +++ b/packages/react-charting/src/components/HorizontalBarChartWithAxis/__snapshots__/HorizontalBarChartWithAxis.test.tsx.snap @@ -41,7 +41,7 @@ exports[`HorizontalBarChartWithAxis - mouse events Should render callout correct "display": "block", } } - width={140} + width={0} > @@ -139,7 +139,7 @@ exports[`HorizontalBarChartWithAxis - mouse events Should render callout correct onMouseLeave={[Function]} onMouseOver={[Function]} role="img" - width={50} + width={-37.5} x={40} y={106} /> @@ -160,7 +160,7 @@ exports[`HorizontalBarChartWithAxis - mouse events Should render callout correct onMouseLeave={[Function]} onMouseOver={[Function]} role="img" - width={80} + width={-40} x={40} y={192.7} /> @@ -181,7 +181,7 @@ exports[`HorizontalBarChartWithAxis - mouse events Should render callout correct onMouseLeave={[Function]} onMouseOver={[Function]} role="img" - width={20} + width={-15} x={40} y={233.5} /> diff --git a/packages/react-charting/src/components/LineChart/LineChart.base.tsx b/packages/react-charting/src/components/LineChart/LineChart.base.tsx index 46317765e2a00..9542bb99ba65a 100644 --- a/packages/react-charting/src/components/LineChart/LineChart.base.tsx +++ b/packages/react-charting/src/components/LineChart/LineChart.base.tsx @@ -143,6 +143,10 @@ export interface ILineChartState extends IBasestate { } export class LineChartBase extends React.Component { + public static defaultProps: Partial = { + enableReflow: true, + }; + private _points: LineChartDataWithIndex[]; // eslint-disable-next-line @typescript-eslint/no-explicit-any private _calloutPoints: any[]; diff --git a/packages/react-charting/src/components/VerticalBarChart/__snapshots__/VerticalBarChart.test.tsx.snap b/packages/react-charting/src/components/VerticalBarChart/__snapshots__/VerticalBarChart.test.tsx.snap index 83abb2dcdcc2a..4ef68b953b603 100644 --- a/packages/react-charting/src/components/VerticalBarChart/__snapshots__/VerticalBarChart.test.tsx.snap +++ b/packages/react-charting/src/components/VerticalBarChart/__snapshots__/VerticalBarChart.test.tsx.snap @@ -41,7 +41,7 @@ exports[`VerticalBarChart - mouse events Should render callout correctly on mous "display": "block", } } - width={126} + width={0} > 50.0k @@ -196,7 +196,7 @@ exports[`VerticalBarChart - mouse events Should render callout correctly on mous onMouseOver={[Function]} role="img" width={16} - x={80.6923076923077} + x={-40.46153846153846} y={122} /> 30.0k @@ -748,7 +748,7 @@ exports[`VerticalBarChart - mouse events Should render customized callout on mou "display": "block", } } - width={126} + width={0} > 50.0k @@ -903,7 +903,7 @@ exports[`VerticalBarChart - mouse events Should render customized callout on mou onMouseOver={[Function]} role="img" width={16} - x={80.6923076923077} + x={-40.46153846153846} y={122} /> 30.0k diff --git a/packages/react-charting/src/components/VerticalStackedBarChart/__snapshots__/VerticalStackedBarChart.test.tsx.snap b/packages/react-charting/src/components/VerticalStackedBarChart/__snapshots__/VerticalStackedBarChart.test.tsx.snap index 360132334a360..91e13ed176a12 100644 --- a/packages/react-charting/src/components/VerticalStackedBarChart/__snapshots__/VerticalStackedBarChart.test.tsx.snap +++ b/packages/react-charting/src/components/VerticalStackedBarChart/__snapshots__/VerticalStackedBarChart.test.tsx.snap @@ -41,7 +41,7 @@ exports[`VerticalStackedBarChart - mouse events Should render callout correctly "display": "block", } } - width={116} + width={0} > @@ -241,7 +241,7 @@ exports[`VerticalStackedBarChart - mouse events Should render callout correctly role="img" textAnchor="middle" transform="translate(0, 0)" - x={80} + x={-36} y={23.807692307692307} > 50 @@ -690,7 +690,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout "display": "block", } } - width={116} + width={0} > @@ -890,7 +890,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout role="img" textAnchor="middle" transform="translate(0, 0)" - x={80} + x={-36} y={23.807692307692307} > 50 @@ -1257,7 +1257,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout "display": "block", } } - width={116} + width={0} > @@ -1439,7 +1439,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout role="img" textAnchor="middle" transform="translate(0, 0)" - x={80} + x={-36} y={23.807692307692307} > 50 @@ -1455,7 +1455,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout strokeWidth={3} transform="translate(0, 0)" x1={56} - x2={80} + x2={-36} y1={201.4423076923077} y2={127.88461538461539} /> @@ -1472,7 +1472,7 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout visibility="visibility" /> Date: Mon, 19 Jun 2023 21:27:46 +0530 Subject: [PATCH 5/5] add comment --- packages/react-charting/src/utilities/utilities.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-charting/src/utilities/utilities.ts b/packages/react-charting/src/utilities/utilities.ts index 3c7be1639fb63..580cac88d8a07 100644 --- a/packages/react-charting/src/utilities/utilities.ts +++ b/packages/react-charting/src/utilities/utilities.ts @@ -244,6 +244,7 @@ export function createDateXAxis( } const tickValues = (tickParams.tickValues ?? xAxisScale.ticks(xAxisCount)).map((val, idx) => { const tickFormat = xAxis.tickFormat(); + // val is a Date object. So when the tick format is not set, format val as a string to calculate its width return tickFormat ? tickFormat(val, idx) : multiFormat(val as Date); }); return { xScale: xAxisScale, tickValues };