Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Fix overlapping axis labels on smaller viewports",
"packageName": "@fluentui/react-charting",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -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]}
Expand Down Expand Up @@ -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]}
Expand Down Expand Up @@ -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]}
Expand Down Expand Up @@ -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]}
Expand Down Expand Up @@ -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]}
Expand Down Expand Up @@ -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]}
Expand Down Expand Up @@ -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]}
Expand Down Expand Up @@ -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]}
Expand Down Expand Up @@ -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]}
Expand Down Expand Up @@ -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]}
Expand Down Expand Up @@ -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]}
Expand Down Expand Up @@ -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]}
Expand Down Expand Up @@ -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]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ICartesianChartStyleProps,
IModifiedCartesianChartProps,
IYValueHover,
IHorizontalBarChartWithAxisDataPoint,
} from '../../index';
import {
ChartHoverCard,
Expand All @@ -28,7 +29,7 @@ import {
rotateXAxisLabels,
Points,
pointTypes,
calculateLongestYAxisLabel,
calculateLongestLabelWidth,
createYAxisLabels,
ChartTypes,
} from '../../utilities/index';
Expand Down Expand Up @@ -73,6 +74,7 @@ export class CartesianChartBase extends React.Component<IModifiedCartesianChartP
private idForGraph: string;
private _reqID: number;
private _isRtl: boolean = getRTL();
private _tickValues: (string | number)[];

// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _xScale: any;
Expand Down Expand Up @@ -118,7 +120,10 @@ export class CartesianChartBase extends React.Component<IModifiedCartesianChartP
this.props.showYAxisLables &&
this.yAxisElement
) {
const maxYAxisLabelLength = calculateLongestYAxisLabel(this.props.points, this.yAxisElement!);
const maxYAxisLabelLength = calculateLongestLabelWidth(
this.props.points.map((point: IHorizontalBarChartWithAxisDataPoint) => point.y),
`.${this._classNames.yAxis} text`,
);
if (this.state.startFromX !== maxYAxisLabelLength) {
this.setState({
startFromX: maxYAxisLabelLength,
Expand Down Expand Up @@ -166,7 +171,10 @@ export class CartesianChartBase extends React.Component<IModifiedCartesianChartP
this.props.showYAxisLables &&
this.yAxisElement
) {
const maxYAxisLabelLength = calculateLongestYAxisLabel(this.props.points, this.yAxisElement!);
const maxYAxisLabelLength = calculateLongestLabelWidth(
this.props.points.map((point: IHorizontalBarChartWithAxisDataPoint) => point.y),
`.${this._classNames.yAxis} text`,
);
if (this.state.startFromX !== maxYAxisLabelLength) {
this.setState({
startFromX: maxYAxisLabelLength,
Expand Down Expand Up @@ -257,27 +265,34 @@ export class CartesianChartBase extends React.Component<IModifiedCartesianChartP
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let xScale: any;
let tickValues: (string | number)[];
switch (this.props.xAxisType!) {
case XAxisTypes.NumericAxis:
xScale = createNumericXAxis(XAxisParams, this.props.chartType, culture);
({ xScale, tickValues } = createNumericXAxis(XAxisParams, this.props.chartType, culture));
break;
case XAxisTypes.DateAxis:
xScale = createDateXAxis(
({ xScale, tickValues } = createDateXAxis(
XAxisParams,
this.props.tickParams!,
culture,
dateLocalizeOptions,
timeFormatLocale,
customDateTimeFormatter,
);
));
break;
case XAxisTypes.StringAxis:
xScale = createStringXAxis(XAxisParams, this.props.tickParams!, this.props.datasetForXAxisDomain!, culture);
({ xScale, tickValues } = createStringXAxis(
XAxisParams,
this.props.tickParams!,
this.props.datasetForXAxisDomain!,
culture,
));
break;
default:
xScale = createNumericXAxis(XAxisParams, this.props.chartType, culture);
({ xScale, tickValues } = createNumericXAxis(XAxisParams, this.props.chartType, culture));
}
this._xScale = xScale;
this._tickValues = tickValues;

/*
* To enable wrapping of x axis tick values or to display complete x axis tick values,
Expand Down Expand Up @@ -404,7 +419,7 @@ export class CartesianChartBase extends React.Component<IModifiedCartesianChartP
ref={(rootElem: HTMLDivElement) => (this.chartContainer = rootElem)}
onMouseLeave={this._onChartLeave}
>
<FocusZone direction={focusDirection} {...svgFocusZoneProps}>
<FocusZone direction={focusDirection} className={this._classNames.chartWrapper} {...svgFocusZoneProps}>
<svg
width={svgDimensions.width}
height={svgDimensions.height}
Expand Down Expand Up @@ -647,7 +662,9 @@ export class CartesianChartBase extends React.Component<IModifiedCartesianChartP
}
if (this.props.parentRef || this.chartContainer) {
const container = this.props.parentRef ? this.props.parentRef : this.chartContainer;
const currentContainerWidth = container.getBoundingClientRect().width;
const currentContainerWidth = this.props.enableReflow
? Math.max(container.getBoundingClientRect().width, this._calculateChartMinWidth())
: container.getBoundingClientRect().width;
const currentContainerHeight =
container.getBoundingClientRect().height > legendContainerHeight
? container.getBoundingClientRect().height
Expand Down Expand Up @@ -682,4 +699,56 @@ export class CartesianChartBase extends React.Component<IModifiedCartesianChartP
private _onChartLeave = (): void => {
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;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export const getStyles = (props: ICartesianChartStyleProps): ICartesianChartStyl
},
className,
],
chartWrapper: {
overflow: 'auto',
},
xAxis: {
selectors: {
text: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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<SVGSVGElement>;

/**
* 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 {
Expand Down
Loading