Skip to content

Commit

Permalink
Make blank cells in heatmap chart accessible (#31225)
Browse files Browse the repository at this point in the history
  • Loading branch information
krkshitij committed May 3, 2024
1 parent 1fbc1fe commit bd9a5d6
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Make blank cells in heatmap chart accessible",
"packageName": "@fluentui/react-charting",
"email": "kumarkshitij@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,9 @@ export class HeatMapChartBase extends React.Component<IHeatMapChartProps, IHeatM
/** Show the callout if highlighted rectangle is focused and Hide it if unhighlighted rectangle is focused */
isCalloutVisible: this.state.selectedLegend === '' || this.state.selectedLegend === data.legend,
calloutYValue: `${data.rectText}`,
calloutTextColor: this._colorScale(data.value),
calloutTextColor: Number.isNaN(data.value)
? this.props.theme!.semanticColors.bodyText
: this._colorScale(data.value),
calloutLegend: data.legend,
ratio: data.ratio || null,
descriptionMessage: data.descriptionMessage || '',
Expand All @@ -261,7 +263,9 @@ export class HeatMapChartBase extends React.Component<IHeatMapChartProps, IHeatM
/** Show the callout if highlighted rectangle is hovered and Hide it if unhighlighted rectangle is hovered */
isCalloutVisible: this.state.selectedLegend === '' || this.state.selectedLegend === data.legend,
calloutYValue: `${data.rectText}`,
calloutTextColor: this._colorScale(data.value),
calloutTextColor: Number.isNaN(data.value)
? this.props.theme!.semanticColors.bodyText
: this._colorScale(data.value),
calloutLegend: data.legend,
ratio: data.ratio || null,
descriptionMessage: data.descriptionMessage || '',
Expand Down Expand Up @@ -294,45 +298,81 @@ export class HeatMapChartBase extends React.Component<IHeatMapChartProps, IHeatM
* yAxisDataPoint is noting but the DataPoint
* which will be rendered on the y-axis
*/
yAxisDataPoints.forEach((yAxisDataPoint: string, index1: number) => {
/**
* dataPointObject is an object where it contains information on single
* data point such as x, y , value, rectText property of the rectangle
*/
this._dataSet[yAxisDataPoint].forEach((dataPointObject: FlattenData, index2: number) => {
const id = `x${index1}y${index2}`;
const rectElement: JSX.Element = (
<g
key={id}
role="img"
aria-label={this._getAriaLabel(dataPointObject)}
data-is-focusable={this._legendHighlighted(dataPointObject.legend) || this._noLegendHighlighted()}
fillOpacity={this._getOpacity(dataPointObject.legend)}
transform={`translate(${this._xAxisScale(dataPointObject.x)}, ${this._yAxisScale(dataPointObject.y)})`}
ref={(gElement: SVGGElement) => {
this._rectRefCallback(gElement, id, dataPointObject);
}}
onFocus={this._onRectFocus.bind(this, id, dataPointObject)}
onBlur={this._onRectBlurOrMouseOut}
onMouseOver={this._onRectMouseOver.bind(this, id, dataPointObject)}
onMouseOut={this._onRectBlurOrMouseOut}
>
<rect
fill={this._colorScale(dataPointObject.value)}
width={this._xAxisScale.bandwidth()}
height={this._yAxisScale.bandwidth()}
onClick={dataPointObject.onClick}
/>
<text
dominantBaseline={'middle'}
textAnchor={'middle'}
className={this._classNames.text}
transform={`translate(${this._xAxisScale.bandwidth() / 2}, ${this._yAxisScale.bandwidth() / 2})`}
yAxisDataPoints.forEach((yAxisDataPoint: string) => {
let index = 0;
this._stringXAxisDataPoints.forEach((xAxisDataPoint: string) => {
let rectElement: JSX.Element;
const id = `x${xAxisDataPoint}y${yAxisDataPoint}`;
if (this._dataSet[yAxisDataPoint][index]?.x === xAxisDataPoint) {
/**
* dataPointObject is an object where it contains information on single
* data point such as x, y , value, rectText property of the rectangle
*/
const dataPointObject = this._dataSet[yAxisDataPoint][index];
rectElement = (
<g
key={id}
role="img"
aria-label={this._getAriaLabel(dataPointObject)}
data-is-focusable={this._legendHighlighted(dataPointObject.legend) || this._noLegendHighlighted()}
fillOpacity={this._getOpacity(dataPointObject.legend)}
transform={`translate(${this._xAxisScale(dataPointObject.x)}, ${this._yAxisScale(dataPointObject.y)})`}
ref={(gElement: SVGGElement) => {
this._rectRefCallback(gElement, id, dataPointObject);
}}
onFocus={this._onRectFocus.bind(this, id, dataPointObject)}
onBlur={this._onRectBlurOrMouseOut}
onMouseOver={this._onRectMouseOver.bind(this, id, dataPointObject)}
onMouseOut={this._onRectBlurOrMouseOut}
>
<rect
fill={this._colorScale(dataPointObject.value)}
width={this._xAxisScale.bandwidth()}
height={this._yAxisScale.bandwidth()}
onClick={dataPointObject.onClick}
/>
<text
dominantBaseline={'middle'}
textAnchor={'middle'}
className={this._classNames.text}
transform={`translate(${this._xAxisScale.bandwidth() / 2}, ${this._yAxisScale.bandwidth() / 2})`}
>
{convertToLocaleString(dataPointObject.rectText, this.props.culture)}
</text>
</g>
);
index++;
} else {
const dataPointObject: FlattenData = {
x: xAxisDataPoint,
y: yAxisDataPoint,
value: NaN,
rectText: 'No data available',
legend: '',
};
rectElement = (
<g
key={id}
role="img"
aria-label={this._getAriaLabel(dataPointObject)}
data-is-focusable={this._noLegendHighlighted()}
transform={`translate(${this._xAxisScale(dataPointObject.x)}, ${this._yAxisScale(dataPointObject.y)})`}
ref={(gElement: SVGGElement) => {
this._rectRefCallback(gElement, id, dataPointObject);
}}
onFocus={this._onRectFocus.bind(this, id, dataPointObject)}
onBlur={this._onRectBlurOrMouseOut}
onMouseOver={this._onRectMouseOver.bind(this, id, dataPointObject)}
onMouseOut={this._onRectBlurOrMouseOut}
>
{convertToLocaleString(dataPointObject.rectText, this.props.culture)}
</text>
</g>
);
<rect
fill={this.props.theme!.semanticColors.bodyBackground}
width={this._xAxisScale.bandwidth()}
height={this._yAxisScale.bandwidth()}
/>
</g>
);
}
rectangles.push(rectElement);
});
});
Expand Down

0 comments on commit bd9a5d6

Please sign in to comment.