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" +} 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..e3bb0550ee056 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 +699,56 @@ export class CartesianChartBase extends React.Component { this.props.onChartMouseLeave && this.props.onChartMouseLeave(); }; + + private _calculateChartMinWidth = (): number => { + let labelWidth = 10; // Total padding on the left and right sides of the label + + // 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 minDomainMargin = 8; + minChartWidth += minDomainMargin * 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..982786f414379 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 { @@ -369,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/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..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 @@ -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]} @@ -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/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/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..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 @@ -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]} @@ -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]} @@ -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..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 @@ -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]} @@ -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]} @@ -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]} @@ -1931,6 +1940,9 @@ exports[`VerticalStackedBarChart snapShot testing Should not render bar labels 1 &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone42" onFocus={[Function]} onKeyDown={[Function]} @@ -2288,6 +2300,9 @@ exports[`VerticalStackedBarChart snapShot testing renders VerticalStackedBarChar &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone3" onFocus={[Function]} onKeyDown={[Function]} @@ -2645,6 +2660,9 @@ exports[`VerticalStackedBarChart snapShot testing renders enabledLegendsWrapLine &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone17" onFocus={[Function]} onKeyDown={[Function]} @@ -2982,6 +3000,9 @@ exports[`VerticalStackedBarChart snapShot testing renders hideLegend correctly 1 &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone8" onFocus={[Function]} onKeyDown={[Function]} @@ -3089,6 +3110,9 @@ exports[`VerticalStackedBarChart snapShot testing renders hideTooltip correctly &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone12" onFocus={[Function]} onKeyDown={[Function]} @@ -3446,6 +3470,9 @@ exports[`VerticalStackedBarChart snapShot testing renders isCalloutForStack corr &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone32" onFocus={[Function]} onKeyDown={[Function]} @@ -3803,6 +3830,9 @@ exports[`VerticalStackedBarChart snapShot testing renders showXAxisLablesTooltip &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone22" onFocus={[Function]} onKeyDown={[Function]} @@ -4160,6 +4190,9 @@ exports[`VerticalStackedBarChart snapShot testing renders wrapXAxisLables correc &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone27" onFocus={[Function]} onKeyDown={[Function]} @@ -4517,6 +4550,9 @@ exports[`VerticalStackedBarChart snapShot testing renders yAxisTickFormat correc &:focus { outline: none; } + { + overflow: auto; + } data-focuszone-id="FocusZone37" onFocus={[Function]} onKeyDown={[Function]} diff --git a/packages/react-charting/src/utilities/utilities.ts b/packages/react-charting/src/utilities/utilities.ts index 070df8d0dc37e..580cac88d8a07 100644 --- a/packages/react-charting/src/utilities/utilities.ts +++ b/packages/react-charting/src/utilities/utilities.ts @@ -166,18 +166,20 @@ export function createNumericXAxis(xAxisParams: IXAxisParams, chartType: ChartTy if (xAxisElement) { d3Select(xAxisElement).call(xAxis).selectAll('text').attr('aria-hidden', 'true'); } - return xAxisScale; + const tickValues = xAxisScale.ticks(xAxisCount).map(xAxis.tickFormat()!); + return { xScale: xAxisScale, tickValues }; } -function multiFormat(date: Date, locale: d3TimeFormat.TimeLocaleObject) { - const formatMillisecond = locale.format('.%L'); - const formatSecond = locale.format(':%S'); - const formatMinute = locale.format('%I:%M'); - const formatHour = locale.format('%I %p'); - const formatDay = locale.format('%a %d'); - const formatWeek = locale.format('%b %d'); - const formatMonth = locale.format('%B'); - const formatYear = locale.format('%Y'); +function multiFormat(date: Date, locale?: d3TimeFormat.TimeLocaleObject) { + const timeFormat = locale ? locale.format : d3TimeFormat.timeFormat; + const formatMillisecond = timeFormat('.%L'); + const formatSecond = timeFormat(':%S'); + const formatMinute = timeFormat('%I:%M'); + const formatHour = timeFormat('%I %p'); + const formatDay = timeFormat('%a %d'); + const formatWeek = timeFormat('%b %d'); + const formatMonth = timeFormat('%B'); + const formatYear = timeFormat('%Y'); return ( d3TimeSecond(date) < date @@ -240,7 +242,12 @@ export function createDateXAxis( if (xAxisElement) { d3Select(xAxisElement).call(xAxis).selectAll('text').attr('aria-hidden', 'true'); } - return xAxisScale; + 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 }; } /** @@ -283,7 +290,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 +732,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 = '600 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)