@@ -627,7 +627,6 @@ export const LineChart: React.FunctionComponent<LineChartProps> = React.forwardR
627627 stroke = { activePoint === circleId ? lineColor : '' }
628628 role = "img"
629629 aria-label = { _points [ i ] . data [ 0 ] . text ?? _getAriaLabel ( i , 0 ) }
630- data-is-focusable = { isLegendSelected }
631630 ref = { ( e : SVGCircleElement | null ) => {
632631 _refCallback ( e ! , circleId ) ;
633632 } }
@@ -724,7 +723,6 @@ export const LineChart: React.FunctionComponent<LineChartProps> = React.forwardR
724723 key = { lineId }
725724 d = { line ( lineData ) ! }
726725 fill = "transparent"
727- data-is-focusable = { true }
728726 stroke = { lineColor }
729727 strokeWidth = { strokeWidth }
730728 strokeLinecap = { _points [ i ] . lineOptions ?. strokeLinecap ?? 'round' }
@@ -744,7 +742,7 @@ export const LineChart: React.FunctionComponent<LineChartProps> = React.forwardR
744742 key = { lineId }
745743 d = { line ( lineData ) ! }
746744 fill = "transparent"
747- data-is-focusable = { false }
745+ tabIndex = { - 1 }
748746 stroke = { lineColor }
749747 strokeWidth = { strokeWidth }
750748 strokeLinecap = { _points [ i ] . lineOptions ?. strokeLinecap ?? 'round' }
@@ -764,6 +762,7 @@ export const LineChart: React.FunctionComponent<LineChartProps> = React.forwardR
764762 cy = { 0 }
765763 fill = { tokens . colorNeutralBackground1 }
766764 strokeWidth = { DEFAULT_LINE_STROKE_SIZE }
765+ tabIndex = { isLegendSelected ? 0 : undefined }
767766 stroke = { lineColor }
768767 visibility = { 'hidden' }
769768 onMouseMove = { event => _onMouseOverLargeDataset ( i , verticaLineHeight , event , yScale ) }
@@ -800,11 +799,13 @@ export const LineChart: React.FunctionComponent<LineChartProps> = React.forwardR
800799 ? tokens . colorNeutralBackground1
801800 : perPointColor || _points [ i ] ?. color || lineColor
802801 }
802+ tabIndex = { isLegendSelected ? 0 : undefined }
803803 stroke = { perPointColor || lineColor }
804804 strokeWidth = { 1 }
805805 opacity = { isLegendSelected ? 1 : 0.1 }
806- onMouseMove = { _onMouseOverLargeDataset . bind ( i , verticaLineHeight , yScale ) }
807- onMouseOver = { _onMouseOverLargeDataset . bind ( i , verticaLineHeight , yScale ) }
806+ onMouseMove = { event => _onMouseOverLargeDataset ( i , verticaLineHeight , event , yScale ) }
807+ onMouseOver = { event => _onMouseOverLargeDataset ( i , verticaLineHeight , event , yScale ) }
808+ onFocus = { event => _onFocusLargeDataset ( i , verticaLineHeight , event , yScale , k ) }
808809 onMouseOut = { _handleMouseOut }
809810 /> ,
810811 ) ;
@@ -852,7 +853,7 @@ export const LineChart: React.FunctionComponent<LineChartProps> = React.forwardR
852853 r = { currentMarkerSize ? ( currentMarkerSize ! * extraMaxPixels ) / maxMarkerSize : 4 }
853854 cx = { xPoint1 }
854855 cy = { yPoint1 }
855- data-is-focusable = { isLegendSelected }
856+ tabIndex = { isLegendSelected ? 0 : undefined }
856857 onMouseOver = { event =>
857858 _handleHover (
858859 x1 ,
@@ -925,7 +926,6 @@ export const LineChart: React.FunctionComponent<LineChartProps> = React.forwardR
925926 id = { circleId }
926927 key = { circleId }
927928 d = { path }
928- data-is-focusable = { isLegendSelected }
929929 onMouseOver = { ( event : React . MouseEvent < SVGElement > ) =>
930930 _handleHover (
931931 x1 ,
@@ -1006,7 +1006,7 @@ export const LineChart: React.FunctionComponent<LineChartProps> = React.forwardR
10061006 r = { currentMarkerSize ? ( currentMarkerSize ! * extraMaxPixels ) / maxMarkerSize : 4 }
10071007 cx = { xPoint2 }
10081008 cy = { yPoint2 }
1009- data-is-focusable = { isLegendSelected }
1009+ tabIndex = { isLegendSelected ? 0 : undefined }
10101010 onMouseOver = { event =>
10111011 _handleHover (
10121012 x2 ,
@@ -1081,7 +1081,6 @@ export const LineChart: React.FunctionComponent<LineChartProps> = React.forwardR
10811081 id = { lastCircleId }
10821082 key = { lastCircleId }
10831083 d = { path }
1084- data-is-focusable = { isLegendSelected }
10851084 onMouseOver = { ( event : React . MouseEvent < SVGElement > ) =>
10861085 _handleHover (
10871086 x2 ,
@@ -1445,6 +1444,98 @@ export const LineChart: React.FunctionComponent<LineChartProps> = React.forwardR
14451444 _refArray . push ( { index : legendTitle , refElement : element } ) ;
14461445 }
14471446
1447+ // Helper function to update highlight circle, vertical line, and callout for large datasets
1448+ const _updateLargeDatasetHighlightAndCallout = (
1449+ linenumber : number ,
1450+ lineHeight : number ,
1451+ pointToHighlight : LineChartDataPoint ,
1452+ xAxisCalloutData : string | undefined ,
1453+ formattedDate : string | number ,
1454+ yScale : ScaleLinear < number , number > ,
1455+ ) => {
1456+ // Check if this point is plottable. If not, close the popover and return.
1457+ const xPoint = _xAxisScale ( pointToHighlight . x ) ;
1458+ const yPoint = yScale ( pointToHighlight . y ) ;
1459+ if ( ! isPlottable ( xPoint , yPoint ) ) {
1460+ return ;
1461+ }
1462+
1463+ const found = findCalloutPoints ( calloutPointsRef . current , pointToHighlight . x ) as
1464+ | CustomizedCalloutData
1465+ | undefined ;
1466+
1467+ const pointToHighlightUpdated =
1468+ nearestCircleToHighlight === null ||
1469+ ( nearestCircleToHighlight !== null &&
1470+ pointToHighlight !== null &&
1471+ ( nearestCircleToHighlight . x !== pointToHighlight . x || nearestCircleToHighlight . y !== pointToHighlight . y ) ) ;
1472+
1473+ // if no points need to be called out then don't show vertical line and callout card
1474+ if ( found && pointToHighlightUpdated ) {
1475+ _uniqueCallOutID = `#${ _staticHighlightCircle } _${ linenumber } ` ;
1476+
1477+ d3Select ( `#${ _staticHighlightCircle } _${ linenumber } ` )
1478+ . attr ( 'cx' , `${ xPoint } ` )
1479+ . attr ( 'cy' , `${ yPoint } ` )
1480+ . attr ( 'visibility' , 'visibility' ) ;
1481+
1482+ d3Select ( `#${ _verticalLine } ` )
1483+ . attr ( 'transform' , ( ) => `translate(${ xPoint } , ${ yPoint } )` )
1484+ . attr ( 'visibility' , 'visibility' )
1485+ . attr ( 'y2' , `${ lineHeight - 5 - yPoint } ` ) ;
1486+
1487+ const targetElement = document . getElementById ( `${ _staticHighlightCircle } _${ linenumber } ` ) ;
1488+ const rect = targetElement ! . getBoundingClientRect ( ) ;
1489+ setNearestCircleToHighlight ( pointToHighlight ) ;
1490+ updatePosition ( rect . x , rect . y ) ;
1491+ setStackCalloutProps ( found ! ) ;
1492+ setYValueHover ( found . values ) ;
1493+ setDataPointCalloutProps ( found ! ) ;
1494+ xAxisCalloutData ? setHoverXValue ( xAxisCalloutData ) : setHoverXValue ( formattedDate ) ;
1495+ setActivePoint ( '' ) ;
1496+ }
1497+
1498+ if ( ! found ) {
1499+ setPopoverOpen ( false ) ;
1500+ setNearestCircleToHighlight ( pointToHighlight ) ;
1501+ setActivePoint ( '' ) ;
1502+ }
1503+ } ;
1504+
1505+ const _onFocusLargeDataset = (
1506+ linenumber : number ,
1507+ lineHeight : number ,
1508+ focusEvent : React . FocusEvent < SVGRectElement | SVGPathElement | SVGCircleElement > ,
1509+ yScale : ScaleLinear < number , number > ,
1510+ pointIndex : number ,
1511+ ) => {
1512+ focusEvent . persist ( ) ;
1513+ const { data } = props ;
1514+ const { lineChartData } = data ;
1515+
1516+ // For focus events, we use the provided point index directly
1517+ const pointToHighlight : LineChartDataPoint = lineChartData ! [ linenumber ] . data [ pointIndex ] as LineChartDataPoint ;
1518+
1519+ if ( ! pointToHighlight ) {
1520+ return ;
1521+ }
1522+
1523+ const { xAxisCalloutData } = pointToHighlight ;
1524+ const formattedDate : string | number =
1525+ pointToHighlight . x instanceof Date
1526+ ? formatDateToLocaleString ( pointToHighlight . x , props . culture , props . useUTC as boolean )
1527+ : pointToHighlight . x ;
1528+
1529+ _updateLargeDatasetHighlightAndCallout (
1530+ linenumber ,
1531+ lineHeight ,
1532+ pointToHighlight ,
1533+ xAxisCalloutData ,
1534+ formattedDate ,
1535+ yScale ,
1536+ ) ;
1537+ } ;
1538+
14481539 const _onMouseOverLargeDataset = (
14491540 linenumber : number ,
14501541 lineHeight : number ,
@@ -1495,55 +1586,20 @@ export const LineChart: React.FunctionComponent<LineChartProps> = React.forwardR
14951586 }
14961587
14971588 const { xAxisCalloutData } = lineChartData ! [ linenumber ] . data [ index as number ] ;
1498- const formattedDate =
1589+ const formattedDate : string | number =
14991590 xPointToHighlight instanceof Date
15001591 ? formatDateToLocaleString ( xPointToHighlight , props . culture , props . useUTC as boolean )
15011592 : xPointToHighlight ;
1502- const found = findCalloutPoints ( calloutPointsRef . current , xPointToHighlight ) as CustomizedCalloutData | undefined ;
15031593 const pointToHighlight : LineChartDataPoint = lineChartData ! [ linenumber ] . data [ index ! ] as LineChartDataPoint ;
15041594
1505- // Check if this point is plottable. If not, close the popover and return.
1506- const xPoint = _xAxisScale ( pointToHighlight . x ) ;
1507- const yPoint = yScale ( pointToHighlight . y ) ;
1508- if ( ! isPlottable ( xPoint , yPoint ) ) {
1509- return ;
1510- }
1511-
1512- const pointToHighlightUpdated =
1513- nearestCircleToHighlight === null ||
1514- ( nearestCircleToHighlight !== null &&
1515- pointToHighlight !== null &&
1516- ( nearestCircleToHighlight . x !== pointToHighlight . x || nearestCircleToHighlight . y !== pointToHighlight . y ) ) ;
1517- // if no points need to be called out then don't show vertical line and callout card
1518- if ( found && pointToHighlightUpdated ) {
1519- _uniqueCallOutID = `#${ _staticHighlightCircle } _${ linenumber } ` ;
1520-
1521- d3Select ( `#${ _staticHighlightCircle } _${ linenumber } ` )
1522- . attr ( 'cx' , `${ xPoint } ` )
1523- . attr ( 'cy' , `${ yPoint } ` )
1524- . attr ( 'visibility' , 'visibility' ) ;
1525-
1526- d3Select ( `#${ _verticalLine } ` )
1527- . attr ( 'transform' , ( ) => `translate(${ xPoint } , ${ yPoint } )` )
1528- . attr ( 'visibility' , 'visibility' )
1529- . attr ( 'y2' , `${ lineHeight - 5 - yPoint } ` ) ;
1530-
1531- const targetElement = document . getElementById ( `${ _staticHighlightCircle } _${ linenumber } ` ) ;
1532- const rect = targetElement ! . getBoundingClientRect ( ) ;
1533- setNearestCircleToHighlight ( pointToHighlight ) ;
1534- updatePosition ( rect . x , rect . y ) ;
1535- setStackCalloutProps ( found ! ) ;
1536- setYValueHover ( found . values ) ;
1537- setDataPointCalloutProps ( found ! ) ;
1538- xAxisCalloutData ? setHoverXValue ( xAxisCalloutData ) : setHoverXValue ( formattedDate ) ;
1539- setActivePoint ( '' ) ;
1540- }
1541-
1542- if ( ! found ) {
1543- setPopoverOpen ( false ) ;
1544- setNearestCircleToHighlight ( pointToHighlight ) ;
1545- setActivePoint ( '' ) ;
1546- }
1595+ _updateLargeDatasetHighlightAndCallout (
1596+ linenumber ,
1597+ lineHeight ,
1598+ pointToHighlight ,
1599+ xAxisCalloutData ,
1600+ formattedDate ,
1601+ yScale ,
1602+ ) ;
15471603 } ;
15481604
15491605 function _handleFocus (
@@ -1818,7 +1874,7 @@ export const LineChart: React.FunctionComponent<LineChartProps> = React.forwardR
18181874 props . getCalloutDescriptionMessage && stackCalloutProps
18191875 ? props . getCalloutDescriptionMessage ( stackCalloutProps )
18201876 : undefined ,
1821- 'data-is-focusable' : true ,
1877+ tabIndex : 0 ,
18221878 xAxisCalloutAccessibilityData : xAxisCalloutAccessibilityData ,
18231879 ...props . calloutProps ,
18241880 isPopoverOpen : isPopoverOpen ,
0 commit comments