Canvas: Add option to disable tooltips for one-click elements (#109937)

This commit is contained in:
Adela Almasan
2025-08-28 16:33:58 +00:00
committed by GitHub
parent 90ccc8fc5a
commit 748010bb0b
9 changed files with 39 additions and 7 deletions
@@ -282,6 +282,8 @@ The options are:
- **Enabled** - Show a tooltip when the cursor hovers over an element.
- **Disabled** - Tooltips are not shown on hover.
The **Disable for one-click elements** setting allows hiding tooltips on elements that have one-click functionality enabled. This prevents tooltips from interfering with one-click interactions while still allowing tooltips on other elements.
### Layer options
The **Layer** options let you add elements to the canvas and control its appearance:
@@ -114,6 +114,7 @@ export const defaultCanvasElementOptions: Partial<CanvasElementOptions> = {
};
export interface CanvasTooltip {
disableForOneClick?: boolean;
mode: ui.TooltipDisplayMode;
}
+10 -2
View File
@@ -866,7 +866,8 @@ export class ElementState implements LayerElement {
handleMouseEnter = (event: React.MouseEvent, isSelected: boolean | undefined) => {
const scene = this.getScene();
const shouldHandleTooltip = !scene?.isEditingEnabled && !scene?.tooltipPayload?.isOpen;
const shouldHandleTooltip =
!scene?.isEditingEnabled && (!scene?.tooltipPayload?.isOpen || scene?.tooltipPayload?.element === this);
if (shouldHandleTooltip) {
this.handleTooltip(event);
} else if (!isSelected) {
@@ -933,7 +934,14 @@ export class ElementState implements LayerElement {
handleTooltip = (event: React.MouseEvent) => {
const scene = this.getScene();
if (scene?.tooltipCallback && scene.tooltipMode !== TooltipDisplayMode.None) {
if (!scene || !scene.tooltipCallback) {
return;
}
const shouldDisableForOneClick = scene.tooltipDisableForOneClick && this.oneClickMode !== OneClickMode.Off;
const shouldShowTooltip = scene.tooltipMode !== TooltipDisplayMode.None && !shouldDisableForOneClick;
if (shouldShowTooltip) {
const rect = this.div?.getBoundingClientRect();
scene.tooltipCallback({
anchorPoint: { x: rect?.right ?? event.pageX, y: rect?.top ?? event.pageY },
+11 -4
View File
@@ -5,7 +5,7 @@ import { CSSProperties } from 'react';
import { BehaviorSubject, ReplaySubject, Subject, Subscription } from 'rxjs';
import Selecto from 'selecto';
import { AppEvents, PanelData } from '@grafana/data';
import { AppEvents, PanelData, OneClickMode } from '@grafana/data';
import { locationService } from '@grafana/runtime';
import {
ColorDimensionConfig,
@@ -81,6 +81,7 @@ export class Scene {
shouldPanZoom?: boolean;
zoomToContent?: boolean;
tooltipMode?: TooltipDisplayMode;
tooltipDisableForOneClick?: boolean;
skipNextSelectionBroadcast = false;
ignoreDataUpdate = false;
panel: CanvasPanel;
@@ -152,6 +153,7 @@ export class Scene {
load(options: Options, enableEditing: boolean) {
const { root, showAdvancedTypes, panZoom, zoomToContent, tooltip } = options;
const tooltipMode = tooltip?.mode ?? TooltipDisplayMode.Single;
const tooltipDisableForOneClick = tooltip?.disableForOneClick ?? false;
this.root = new RootElement(
root ?? {
@@ -167,6 +169,7 @@ export class Scene {
this.shouldPanZoom = panZoom;
this.zoomToContent = zoomToContent;
this.tooltipMode = tooltipMode;
this.tooltipDisableForOneClick = tooltipDisableForOneClick;
setTimeout(() => {
if (config.featureToggles.canvasPanelPanZoom) {
@@ -376,8 +379,12 @@ export class Scene {
this.tooltipPayload?.element?.options.actions && this.tooltipPayload.element.options.actions.length > 0;
const isTooltipValid = hasDataLinks || hasActions || this.tooltipPayload?.element?.data?.field;
const isTooltipEnabled = this.tooltipMode !== TooltipDisplayMode.None;
const canShowElementTooltip = !this.isEditingEnabled && isTooltipValid && isTooltipEnabled;
const isCanvasTooltipEnabled = this.tooltipMode !== TooltipDisplayMode.None;
const isTooltipDisabledForOneClick =
this.tooltipDisableForOneClick && this.tooltipPayload?.element?.oneClickMode !== OneClickMode.Off;
const shouldShowElementTooltip =
!this.isEditingEnabled && isTooltipValid && isCanvasTooltipEnabled && !isTooltipDisabledForOneClick;
const sceneDiv = (
<>
@@ -392,7 +399,7 @@ export class Scene {
/>
</Portal>
)}
{canShowElementTooltip && (
{shouldShowElementTooltip && (
<Portal>
<CanvasTooltip scene={this} />
</Portal>
@@ -237,13 +237,16 @@ export class CanvasPanel extends Component<Props, State> {
const panZoomSwitched = this.props.options.panZoom !== nextProps.options.panZoom;
const zoomToContentSwitched = this.props.options.zoomToContent !== nextProps.options.zoomToContent;
const tooltipModeSwitched = this.props.options.tooltip?.mode !== nextProps.options.tooltip?.mode;
const tooltipDisableForOneClickSwitched =
this.props.options.tooltip?.disableForOneClick !== nextProps.options.tooltip?.disableForOneClick;
if (
this.needsReload ||
inlineEditingSwitched ||
shouldShowAdvancedTypesSwitched ||
panZoomSwitched ||
zoomToContentSwitched ||
tooltipModeSwitched
tooltipModeSwitched ||
tooltipDisableForOneClickSwitched
) {
if (inlineEditingSwitched) {
// Replace scene div to prevent selecto instance leaks
@@ -74,6 +74,14 @@ export const addStandardCanvasEditorOptions = (builder: PanelOptionsEditorBuilde
],
},
});
builder.addBooleanSwitch({
path: 'tooltip.disableForOneClick',
name: t('canvas.tooltip-options.label-disable-one-click', 'Disable for one-click elements'),
category,
defaultValue: false,
showIf: (options) => options.tooltip?.mode !== TooltipDisplayMode.None,
});
};
export const plugin = new PanelPlugin<Options>(CanvasPanel)
@@ -91,6 +91,7 @@ composableKinds: PanelCfg: {
} @cuetsy(kind="interface")
CanvasTooltip: {
mode: ui.TooltipDisplayMode
disableForOneClick?: bool
} @cuetsy(kind="interface")
Options: {
@@ -112,6 +112,7 @@ export const defaultCanvasElementOptions: Partial<CanvasElementOptions> = {
};
export interface CanvasTooltip {
disableForOneClick?: boolean;
mode: ui.TooltipDisplayMode;
}
+1
View File
@@ -4019,6 +4019,7 @@
}
},
"tooltip-options": {
"label-disable-one-click": "Disable for one-click elements",
"name-tooltip-mode": "Tooltip mode",
"tooltip-mode-options": {
"label-disabled": "Disabled",