diff --git a/change/@fluentui-react-charting-02e2c197-f212-4bf8-9772-927edb4e640f.json b/change/@fluentui-react-charting-02e2c197-f212-4bf8-9772-927edb4e640f.json new file mode 100644 index 0000000000000..3984dc268c471 --- /dev/null +++ b/change/@fluentui-react-charting-02e2c197-f212-4bf8-9772-927edb4e640f.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Disable focus on non-interactive elements", + "packageName": "@fluentui/react-charting", + "email": "kumarkshitij@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/packages/react-charting/src/components/HorizontalBarChart/HorizontalBarChart.base.tsx b/packages/react-charting/src/components/HorizontalBarChart/HorizontalBarChart.base.tsx index 7427b3660216e..29f0e0c2efc8b 100644 --- a/packages/react-charting/src/components/HorizontalBarChart/HorizontalBarChart.base.tsx +++ b/packages/react-charting/src/components/HorizontalBarChart/HorizontalBarChart.base.tsx @@ -14,8 +14,8 @@ import { import { Callout, DirectionalHint } from '@fluentui/react/lib/Callout'; import { ChartHoverCard, convertToLocaleString, getAccessibleDataObject } from '../../utilities/index'; import { FocusZone, FocusZoneDirection } from '@fluentui/react-focus'; -import { TooltipHost, TooltipOverflowMode } from '@fluentui/react'; import { formatPrefix as d3FormatPrefix } from 'd3-format'; +import { FocusableTooltipText } from '../../utilities/FocusableTooltipText'; const getClassNames = classNamesFunction(); @@ -100,15 +100,11 @@ export class HorizontalBarChartBase extends React.Component
{points!.chartTitle && ( - - - {points!.chartTitle} - - + accessibilityData={points!.chartTitleAccessibilityData} + /> )} {chartDataText}
@@ -225,9 +221,7 @@ export class HorizontalBarChartBase extends React.Component { return this.props.barChartCustomData ? ( -
- {this.props.barChartCustomData(data)} -
+
{this.props.barChartCustomData(data)}
) : ( this._getDefaultTextData(data) ); @@ -240,7 +234,7 @@ export class HorizontalBarChartBase extends React.Component one @@ -96,7 +96,7 @@ exports[`HorizontalBarChart - mouse events Should render callout correctly on mo font-size: 14px; font-weight: 600; } - data-is-focusable={true} + data-is-focusable={false} role="text" > 1,543 @@ -231,7 +231,7 @@ exports[`HorizontalBarChart - mouse events Should render callout correctly on mo role="none" > two @@ -263,7 +263,7 @@ exports[`HorizontalBarChart - mouse events Should render callout correctly on mo font-size: 14px; font-weight: 600; } - data-is-focusable={true} + data-is-focusable={false} role="text" > 800 @@ -574,7 +574,7 @@ exports[`HorizontalBarChart - mouse events Should render customized callout on m role="none" > one @@ -606,7 +606,7 @@ exports[`HorizontalBarChart - mouse events Should render customized callout on m font-size: 14px; font-weight: 600; } - data-is-focusable={true} + data-is-focusable={false} role="text" > 1,543 @@ -741,7 +741,7 @@ exports[`HorizontalBarChart - mouse events Should render customized callout on m role="none" > two @@ -773,7 +773,7 @@ exports[`HorizontalBarChart - mouse events Should render customized callout on m font-size: 14px; font-weight: 600; } - data-is-focusable={true} + data-is-focusable={false} role="text" > 800 @@ -1004,7 +1004,7 @@ exports[`HorizontalBarChart snapShot testing Should not render bar labels in abs role="none" > one @@ -1136,7 +1136,7 @@ exports[`HorizontalBarChart snapShot testing Should not render bar labels in abs role="none" > two @@ -1285,7 +1285,7 @@ exports[`HorizontalBarChart snapShot testing Should render absolute-scale varian role="none" > one @@ -1435,7 +1435,7 @@ exports[`HorizontalBarChart snapShot testing Should render absolute-scale varian role="none" > two diff --git a/packages/react-charting/src/components/StackedBarChart/MultiStackedBarChart.base.tsx b/packages/react-charting/src/components/StackedBarChart/MultiStackedBarChart.base.tsx index eef7f841fd278..900834299ee67 100644 --- a/packages/react-charting/src/components/StackedBarChart/MultiStackedBarChart.base.tsx +++ b/packages/react-charting/src/components/StackedBarChart/MultiStackedBarChart.base.tsx @@ -14,8 +14,8 @@ import { import { Callout, DirectionalHint } from '@fluentui/react/lib/Callout'; import { FocusZone, FocusZoneDirection } from '@fluentui/react-focus'; import { ChartHoverCard, convertToLocaleString, getAccessibleDataObject } from '../../utilities/index'; -import { TooltipHost, TooltipOverflowMode } from '@fluentui/react'; import { formatPrefix as d3FormatPrefix } from 'd3-format'; +import { FocusableTooltipText } from '../../utilities/FocusableTooltipText'; const getClassNames = classNamesFunction(); @@ -258,7 +258,6 @@ export class MultiStackedBarChartBase extends React.Component @@ -297,16 +296,14 @@ export class MultiStackedBarChartBase extends React.Component
{data!.chartTitle && ( - - {data!.chartTitle} - + accessibilityData={data!.chartTitleAccessibilityData} + /> )} {showRatio && ( -
+
{getChartData()} {!hideDenominator && ( @@ -318,7 +315,7 @@ export class MultiStackedBarChartBase extends React.Component {getChartData()}
diff --git a/packages/react-charting/src/components/StackedBarChart/StackedBarChart.base.tsx b/packages/react-charting/src/components/StackedBarChart/StackedBarChart.base.tsx index 54ddd468de6d9..62b1866bf576d 100644 --- a/packages/react-charting/src/components/StackedBarChart/StackedBarChart.base.tsx +++ b/packages/react-charting/src/components/StackedBarChart/StackedBarChart.base.tsx @@ -7,7 +7,7 @@ import { IRefArrayData, IStackedBarChartProps, IStackedBarChartStyleProps, IStac import { Callout, DirectionalHint } from '@fluentui/react/lib/Callout'; import { FocusZone, FocusZoneDirection } from '@fluentui/react-focus'; import { ChartHoverCard, convertToLocaleString, getAccessibleDataObject } from '../../utilities/index'; -import { TooltipHost, TooltipOverflowMode } from '@fluentui/react'; +import { FocusableTooltipText } from '../../utilities/FocusableTooltipText'; const getClassNames = classNamesFunction(); export interface IStackedBarChartState { @@ -107,16 +107,14 @@ export class StackedBarChartBase extends React.Component
{data!.chartTitle && ( - - {data!.chartTitle} - + accessibilityData={data!.chartTitleAccessibilityData} + /> )} {showRatio && ( -
+
{getChartData()} {!this.props.hideDenominator && ( @@ -128,7 +126,7 @@ export class StackedBarChartBase extends React.Component {getChartData()}
diff --git a/packages/react-charting/src/components/StackedBarChart/__snapshots__/MultiStackedBarChart.test.tsx.snap b/packages/react-charting/src/components/StackedBarChart/__snapshots__/MultiStackedBarChart.test.tsx.snap index 8d619ca410f83..768da972c94ff 100644 --- a/packages/react-charting/src/components/StackedBarChart/__snapshots__/MultiStackedBarChart.test.tsx.snap +++ b/packages/react-charting/src/components/StackedBarChart/__snapshots__/MultiStackedBarChart.test.tsx.snap @@ -72,7 +72,7 @@ exports[`MultiStackedBarChart - mouse events Should render callout correctly on role="none" > Monitored @@ -97,7 +97,7 @@ exports[`MultiStackedBarChart - mouse events Should render callout correctly on
Unmonitored @@ -303,7 +303,7 @@ exports[`MultiStackedBarChart - mouse events Should render callout correctly on
Monitored @@ -761,7 +761,7 @@ exports[`MultiStackedBarChart - mouse events Should render customized callout on
Unmonitored @@ -967,7 +967,7 @@ exports[`MultiStackedBarChart - mouse events Should render customized callout on
Monitored @@ -1491,7 +1491,7 @@ exports[`MultiStackedBarChart snapShot testing Should not render bar labels in a role="none" > Unmonitored @@ -1758,7 +1758,7 @@ exports[`MultiStackedBarChart snapShot testing Should render absolute-scale vari role="none" > Monitored @@ -1882,7 +1882,6 @@ exports[`MultiStackedBarChart snapShot testing Should render absolute-scale vari font-size: 12px; font-weight: 600; } - data-is-focusable={true} dominantBaseline="central" role="img" transform="translate(4)" @@ -1950,7 +1949,7 @@ exports[`MultiStackedBarChart snapShot testing Should render absolute-scale vari role="none" > Unmonitored @@ -2074,7 +2073,6 @@ exports[`MultiStackedBarChart snapShot testing Should render absolute-scale vari font-size: 12px; font-weight: 600; } - data-is-focusable={true} dominantBaseline="central" role="img" transform="translate(4)" @@ -2235,7 +2233,7 @@ exports[`MultiStackedBarChart snapShot testing renders MultiStackedBarChart corr role="none" > Monitored @@ -2260,7 +2258,7 @@ exports[`MultiStackedBarChart snapShot testing renders MultiStackedBarChart corr
Unmonitored @@ -2460,7 +2458,7 @@ exports[`MultiStackedBarChart snapShot testing renders MultiStackedBarChart corr
Monitored @@ -2753,7 +2751,7 @@ exports[`MultiStackedBarChart snapShot testing renders hideDenominator correctly
Unmonitored @@ -2943,7 +2941,7 @@ exports[`MultiStackedBarChart snapShot testing renders hideDenominator correctly
Monitored @@ -3226,7 +3224,7 @@ exports[`MultiStackedBarChart snapShot testing renders hideLegend correctly 1`]
Unmonitored @@ -3426,7 +3424,7 @@ exports[`MultiStackedBarChart snapShot testing renders hideLegend correctly 1`]
Monitored @@ -3797,7 +3795,7 @@ exports[`MultiStackedBarChart snapShot testing renders hideRatio correctly 1`] = role="none" > Unmonitored @@ -3822,7 +3820,7 @@ exports[`MultiStackedBarChart snapShot testing renders hideRatio correctly 1`] =
Monitored @@ -4296,7 +4294,7 @@ exports[`MultiStackedBarChart snapShot testing renders hideTooltip correctly 1`]
Unmonitored @@ -4496,7 +4494,7 @@ exports[`MultiStackedBarChart snapShot testing renders hideTooltip correctly 1`]
Stacked bar chart 2nd example @@ -84,7 +84,7 @@ exports[`StackedBarChart - mouse events Should render callout correctly on mouse
Stacked bar chart 2nd example @@ -454,7 +454,7 @@ exports[`StackedBarChart - mouse events Should render customized callout on mous
Stacked bar chart 2nd example @@ -741,7 +741,7 @@ exports[`StackedBarChart snapShot testing renders StackedBarChart correctly 1`]
Stacked bar chart 2nd example @@ -948,7 +948,7 @@ exports[`StackedBarChart snapShot testing renders enabledLegendsWrapLines correc
Stacked bar chart 2nd example @@ -1155,7 +1155,7 @@ exports[`StackedBarChart snapShot testing renders hideDenominator correctly 1`]
Stacked bar chart 2nd example @@ -1352,7 +1352,7 @@ exports[`StackedBarChart snapShot testing renders hideLegend correctly 1`] = `
Stacked bar chart 2nd example @@ -1715,7 +1715,7 @@ exports[`StackedBarChart snapShot testing renders hideTooltip correctly 1`] = ` role="none" > Stacked bar chart 2nd example @@ -1740,7 +1740,7 @@ exports[`StackedBarChart snapShot testing renders hideTooltip correctly 1`] = `
Stacked bar chart 2nd example diff --git a/packages/react-charting/src/components/VerticalStackedBarChart/VerticalStackedBarChart.base.tsx b/packages/react-charting/src/components/VerticalStackedBarChart/VerticalStackedBarChart.base.tsx index fd6d11de38ae0..8f87e8191df4b 100644 --- a/packages/react-charting/src/components/VerticalStackedBarChart/VerticalStackedBarChart.base.tsx +++ b/packages/react-charting/src/components/VerticalStackedBarChart/VerticalStackedBarChart.base.tsx @@ -826,7 +826,6 @@ export class VerticalStackedBarChartBase extends React.Component< y={yPoint - 6} textAnchor="middle" className={this._classNames.barLabel} - data-is-focusable={true} aria-label={`Total: ${barTotalValue}`} role="img" transform={`translate(${xScaleBandwidthTranslate}, 0)`} 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 f65548423df86..c08589f1d6b27 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 @@ -162,7 +162,6 @@ exports[`VerticalStackedBarChart - mouse events Should render callout correctly font-size: 12px; font-weight: 600; } - data-is-focusable={true} role="img" textAnchor="middle" transform="translate(0, 0)" @@ -236,7 +235,6 @@ exports[`VerticalStackedBarChart - mouse events Should render callout correctly font-size: 12px; font-weight: 600; } - data-is-focusable={true} role="img" textAnchor="middle" transform="translate(0, 0)" @@ -810,7 +808,6 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout font-size: 12px; font-weight: 600; } - data-is-focusable={true} role="img" textAnchor="middle" transform="translate(0, 0)" @@ -884,7 +881,6 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout font-size: 12px; font-weight: 600; } - data-is-focusable={true} role="img" textAnchor="middle" transform="translate(0, 0)" @@ -1367,7 +1363,6 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout font-size: 12px; font-weight: 600; } - data-is-focusable={true} role="img" textAnchor="middle" transform="translate(0, 0)" @@ -1432,7 +1427,6 @@ exports[`VerticalStackedBarChart - mouse events Should render customized callout font-size: 12px; font-weight: 600; } - data-is-focusable={true} role="img" textAnchor="middle" transform="translate(0, 0)" diff --git a/packages/react-charting/src/utilities/FocusableTooltipText.tsx b/packages/react-charting/src/utilities/FocusableTooltipText.tsx new file mode 100644 index 0000000000000..96e4d270a8472 --- /dev/null +++ b/packages/react-charting/src/utilities/FocusableTooltipText.tsx @@ -0,0 +1,80 @@ +import * as React from 'react'; +import { hasOverflow, ITooltipHostProps, TooltipHost, TooltipOverflowMode } from '@fluentui/react'; +import { getAccessibleDataObject } from './index'; +import { IAccessibilityProps } from '../types/index'; +import { Async } from '../Utilities'; + +interface IFocusableTooltipTextProps { + className?: ITooltipHostProps['hostClassName']; + content?: ITooltipHostProps['content']; + accessibilityData?: IAccessibilityProps; +} + +interface IFocusableTooltipTextState { + textOverflow: boolean; +} + +/** + * Component to make the text focusable when the overflowed content is clipped + * because of the CSS text-overflow property. + */ +export class FocusableTooltipText extends React.Component { + private _tooltipChild = React.createRef(); + private _resizeObserver?: ResizeObserver; + private _async: Async; + + constructor(props: IFocusableTooltipTextProps) { + super(props); + + this.state = { + textOverflow: false, + }; + + this._async = new Async(this); + } + + public render(): React.ReactNode { + const { className, content, accessibilityData } = this.props; + + return ( + + + {content} + + + ); + } + + public componentDidMount(): void { + const overflowElement = this._getTargetElement(); + if (window.ResizeObserver && overflowElement) { + this._resizeObserver = new ResizeObserver(this._async.debounce(this._checkTextOverflow, 500)); + this._resizeObserver.observe(overflowElement); + } + } + + public componentWillUnmount(): void { + this._resizeObserver?.disconnect(); + this._async.dispose(); + } + + private _checkTextOverflow = (): void => { + const overflowElement = this._getTargetElement(); + const textOverflow = !!overflowElement && hasOverflow(overflowElement); + if (textOverflow !== this.state.textOverflow) { + this.setState({ textOverflow }); + } + }; + + private _getTargetElement = (): HTMLElement | undefined => { + if (!this._tooltipChild.current || !this._tooltipChild.current.parentElement) { + return undefined; + } + + return this._tooltipChild.current.parentElement; + }; +}