From 1620f028b4ad807bf3ccfea4767035973acd75b0 Mon Sep 17 00:00:00 2001 From: Adela Almasan <88068998+adela-almasan@users.noreply.github.com> Date: Tue, 1 Jul 2025 10:27:06 -0500 Subject: [PATCH] TableNG: Fix click events bubbling up (#107156) --- .../src/components/Table/Cells/DefaultCell.tsx | 5 ++--- .../src/components/Table/Cells/ImageCell.tsx | 11 +++++++---- .../components/Table/Cells/JSONViewCell.tsx | 7 ++----- .../Table/DataLinksActionsTooltip.tsx | 2 +- .../Table/TableNG/Cells/AutoCell.tsx | 4 ++-- .../Table/TableNG/Cells/BarGaugeCell.tsx | 4 ++-- .../Table/TableNG/Cells/ImageCell.tsx | 6 ++---- .../Table/TableNG/Cells/JSONCell.tsx | 4 ++-- .../grafana-ui/src/components/Table/utils.ts | 18 ++++++++++++++++++ 9 files changed, 38 insertions(+), 23 deletions(-) diff --git a/packages/grafana-ui/src/components/Table/Cells/DefaultCell.tsx b/packages/grafana-ui/src/components/Table/Cells/DefaultCell.tsx index 1c70685e017..00df617e864 100644 --- a/packages/grafana-ui/src/components/Table/Cells/DefaultCell.tsx +++ b/packages/grafana-ui/src/components/Table/Cells/DefaultCell.tsx @@ -15,6 +15,7 @@ import { getCellColors, getCellOptions, getDataLinksActionsTooltipUtils, + tooltipOnClickHandler, } from '../utils'; export const DefaultCell = (props: TableCellProps) => { @@ -88,9 +89,7 @@ export const DefaultCell = (props: TableCellProps) => { {...rest} className={cellStyle} style={{ ...cellProps.style, cursor: hasMultipleLinksOrActions ? 'context-menu' : 'auto' }} - onClick={({ clientX, clientY }) => { - setTooltipCoords({ clientX, clientY }); - }} + onClick={tooltipOnClickHandler(setTooltipCoords)} > {shouldShowLink ? ( renderSingleLink(links[0], value, getLinkStyle(tableStyles, cellOptions)) diff --git a/packages/grafana-ui/src/components/Table/Cells/ImageCell.tsx b/packages/grafana-ui/src/components/Table/Cells/ImageCell.tsx index 9eb49788371..d0e6fd2b43a 100644 --- a/packages/grafana-ui/src/components/Table/Cells/ImageCell.tsx +++ b/packages/grafana-ui/src/components/Table/Cells/ImageCell.tsx @@ -3,7 +3,12 @@ import { useState } from 'react'; import { getCellLinks } from '../../../utils/table'; import { DataLinksActionsTooltip, renderSingleLink } from '../DataLinksActionsTooltip'; import { TableCellDisplayMode, TableCellProps } from '../types'; -import { DataLinksActionsTooltipCoords, getCellOptions, getDataLinksActionsTooltipUtils } from '../utils'; +import { + tooltipOnClickHandler, + DataLinksActionsTooltipCoords, + getCellOptions, + getDataLinksActionsTooltipUtils, +} from '../utils'; const DATALINKS_HEIGHT_OFFSET = 10; @@ -37,9 +42,7 @@ export const ImageCell = (props: TableCellProps) => { {...cellProps} className={tableStyles.cellContainer} style={{ ...cellProps.style, cursor: hasMultipleLinksOrActions ? 'context-menu' : 'auto' }} - onClick={({ clientX, clientY }) => { - setTooltipCoords({ clientX, clientY }); - }} + onClick={tooltipOnClickHandler(setTooltipCoords)} > {/* If there are data links/actions, we render them with image */} {/* Otherwise we simply render the image */} diff --git a/packages/grafana-ui/src/components/Table/Cells/JSONViewCell.tsx b/packages/grafana-ui/src/components/Table/Cells/JSONViewCell.tsx index e214c600458..e9d94fec7c5 100644 --- a/packages/grafana-ui/src/components/Table/Cells/JSONViewCell.tsx +++ b/packages/grafana-ui/src/components/Table/Cells/JSONViewCell.tsx @@ -7,7 +7,7 @@ import { CellActions } from '../CellActions'; import { DataLinksActionsTooltip, renderSingleLink } from '../DataLinksActionsTooltip'; import { TableCellInspectorMode } from '../TableCellInspector'; import { TableCellProps } from '../types'; -import { DataLinksActionsTooltipCoords, getDataLinksActionsTooltipUtils } from '../utils'; +import { tooltipOnClickHandler, DataLinksActionsTooltipCoords, getDataLinksActionsTooltipUtils } from '../utils'; export function JSONViewCell(props: TableCellProps): JSX.Element { const { cell, tableStyles, cellProps, field, row } = props; @@ -37,10 +37,7 @@ export function JSONViewCell(props: TableCellProps): JSX.Element { return (
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */} -
setTooltipCoords({ clientX, clientY })} - > +
{shouldShowLink ? ( renderSingleLink(links[0], displayValue) ) : shouldShowTooltip ? ( diff --git a/packages/grafana-ui/src/components/Table/DataLinksActionsTooltip.tsx b/packages/grafana-ui/src/components/Table/DataLinksActionsTooltip.tsx index 36327a6ca7b..1bd8774479b 100644 --- a/packages/grafana-ui/src/components/Table/DataLinksActionsTooltip.tsx +++ b/packages/grafana-ui/src/components/Table/DataLinksActionsTooltip.tsx @@ -89,7 +89,7 @@ export const DataLinksActionsTooltip = ({ links, actions, value, coords, onToolt
e.stopPropagation() })} + {...getReferenceProps()} {...getFloatingProps()} style={floatingStyles} className={styles.tooltipWrapper} diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/AutoCell.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/AutoCell.tsx index a3bcdad4db0..3fdcfc85491 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/Cells/AutoCell.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/AutoCell.tsx @@ -8,7 +8,7 @@ import { selectors } from '@grafana/e2e-selectors'; import { useStyles2 } from '../../../../themes/ThemeContext'; import { DataLinksActionsTooltip, renderSingleLink } from '../../DataLinksActionsTooltip'; import { TableCellOptions, TableCellDisplayMode } from '../../types'; -import { DataLinksActionsTooltipCoords, getDataLinksActionsTooltipUtils } from '../../utils'; +import { DataLinksActionsTooltipCoords, getDataLinksActionsTooltipUtils, tooltipOnClickHandler } from '../../utils'; import { AutoCellProps } from '../types'; import { getCellLinks } from '../utils'; @@ -27,7 +27,7 @@ export default function AutoCell({ value, field, justifyContent, rowIdx, cellOpt // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
setTooltipCoords({ clientX, clientY })} + onClick={tooltipOnClickHandler(setTooltipCoords)} style={{ cursor: hasMultipleLinksOrActions ? 'context-menu' : 'auto' }} data-testid={selectors.components.TablePanel.autoCell} > diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/BarGaugeCell.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/BarGaugeCell.tsx index b386ef29879..710a8c65726 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/Cells/BarGaugeCell.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/BarGaugeCell.tsx @@ -5,7 +5,7 @@ import { BarGaugeDisplayMode, BarGaugeValueMode, TableCellDisplayMode } from '@g import { BarGauge } from '../../../BarGauge/BarGauge'; import { DataLinksActionsTooltip, renderSingleLink } from '../../DataLinksActionsTooltip'; -import { DataLinksActionsTooltipCoords, getDataLinksActionsTooltipUtils } from '../../utils'; +import { tooltipOnClickHandler, DataLinksActionsTooltipCoords, getDataLinksActionsTooltipUtils } from '../../utils'; import { BarGaugeCellProps } from '../types'; import { extractPixelValue, getCellOptions, getAlignmentFactor, getCellLinks } from '../utils'; @@ -78,7 +78,7 @@ export const BarGaugeCell = ({ value, field, theme, height, width, rowIdx, actio // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
setTooltipCoords({ clientX, clientY })} + onClick={tooltipOnClickHandler(setTooltipCoords)} > {shouldShowLink ? ( renderSingleLink(links[0], renderComponent()) diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/ImageCell.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/ImageCell.tsx index 348d0aa168c..bc62e266b12 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/Cells/ImageCell.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/ImageCell.tsx @@ -7,7 +7,7 @@ import { GrafanaTheme2 } from '@grafana/data'; import { useStyles2 } from '../../../../themes/ThemeContext'; import { DataLinksActionsTooltip, renderSingleLink } from '../../DataLinksActionsTooltip'; import { TableCellDisplayMode } from '../../types'; -import { DataLinksActionsTooltipCoords, getDataLinksActionsTooltipUtils } from '../../utils'; +import { DataLinksActionsTooltipCoords, getDataLinksActionsTooltipUtils, tooltipOnClickHandler } from '../../utils'; import { ImageCellProps } from '../types'; import { getCellLinks } from '../utils'; @@ -33,9 +33,7 @@ export const ImageCell = ({ cellOptions, field, height, justifyContent, value, r
{ - setTooltipCoords({ clientX, clientY }); - }} + onClick={tooltipOnClickHandler(setTooltipCoords)} > {shouldShowLink ? ( renderSingleLink(links[0], img) diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/JSONCell.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/JSONCell.tsx index 025cf19bac3..2506255cb03 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/Cells/JSONCell.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/JSONCell.tsx @@ -6,7 +6,7 @@ import { GrafanaTheme2 } from '@grafana/data'; import { useStyles2 } from '../../../../themes/ThemeContext'; import { DataLinksActionsTooltip, renderSingleLink } from '../../DataLinksActionsTooltip'; -import { DataLinksActionsTooltipCoords, getDataLinksActionsTooltipUtils } from '../../utils'; +import { tooltipOnClickHandler, DataLinksActionsTooltipCoords, getDataLinksActionsTooltipUtils } from '../../utils'; import { JSONCellProps } from '../types'; import { getCellLinks } from '../utils'; @@ -43,7 +43,7 @@ export const JSONCell = ({ value, justifyContent, field, rowIdx, actions }: JSON // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
setTooltipCoords({ clientX, clientY })} + onClick={tooltipOnClickHandler(setTooltipCoords)} style={{ cursor: hasMultipleLinksOrActions ? 'context-menu' : 'auto' }} > {shouldShowLink ? ( diff --git a/packages/grafana-ui/src/components/Table/utils.ts b/packages/grafana-ui/src/components/Table/utils.ts index 1f1f9f0c50c..f4c9b072b16 100644 --- a/packages/grafana-ui/src/components/Table/utils.ts +++ b/packages/grafana-ui/src/components/Table/utils.ts @@ -775,3 +775,21 @@ export const getDataLinksActionsTooltipUtils = (links: LinkModel[], actions?: Ac return { shouldShowLink, hasMultipleLinksOrActions }; }; + +const shouldTriggerTooltip = (event: React.MouseEvent): boolean => { + return event.target === event.currentTarget; +}; + +/** + * Creates an onClick handler for table cells that only triggers tooltip when clicking directly on the cell + * @param setTooltipCoords - function to set tooltip coordinates + * @returns onClick handler + */ +export const tooltipOnClickHandler = (setTooltipCoords: (coords: DataLinksActionsTooltipCoords) => void) => { + return (event: React.MouseEvent) => { + if (shouldTriggerTooltip(event)) { + const { clientX, clientY } = event; + setTooltipCoords({ clientX, clientY }); + } + }; +};