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 });
+ }
+ };
+};