From b4a5fe6c45c7d30cd459fe07a635e7732b2d65c0 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 7 Oct 2025 11:56:26 +0530 Subject: [PATCH] fix: tooltip appears at bottom of page instead of near hovered element on-behalf-of: @Mermaid-Chart --- .../mermaid/src/diagrams/class/classDb.ts | 42 +++++++++++-------- .../mermaid/src/diagrams/flowchart/flowDb.ts | 15 +++++++ 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/packages/mermaid/src/diagrams/class/classDb.ts b/packages/mermaid/src/diagrams/class/classDb.ts index 82ddcf09b..d5a2da794 100644 --- a/packages/mermaid/src/diagrams/class/classDb.ts +++ b/packages/mermaid/src/diagrams/class/classDb.ts @@ -1,4 +1,4 @@ -import { select, type Selection } from 'd3'; +import { select } from 'd3'; import { log } from '../../logger.js'; import { getConfig } from '../../diagram-api/diagramAPI.js'; import common from '../common/common.js'; @@ -474,42 +474,50 @@ export class ClassDB implements DiagramDB { }; private readonly setupToolTips = (element: Element) => { - let tooltipElem: Selection = - select('.mermaidTooltip'); - // @ts-expect-error - Incorrect types - if ((tooltipElem._groups || tooltipElem)[0][0] === null) { + let tooltipElem = select('.mermaidTooltip'); + if (tooltipElem.empty()) { tooltipElem = select('body') .append('div') .attr('class', 'mermaidTooltip') - .style('opacity', 0); + .style('opacity', 0) + .style('position', 'absolute') + .style('text-align', 'center') + .style('max-width', '200px') + .style('padding', '2px') + .style('font-size', '12px') + .style('background', '#ffffde') + .style('border', '1px solid #333') + .style('border-radius', '2px') + .style('pointer-events', 'none') + .style('z-index', '100'); } const svg = select(element).select('svg'); - const nodes = svg.selectAll('g.node'); + const nodes = svg.selectAll('g').filter(function () { + return select(this).attr('title') !== null; + }); + nodes .on('mouseover', (event: MouseEvent) => { const el = select(event.currentTarget as HTMLElement); const title = el.attr('title'); - // Don't try to draw a tooltip if no data is provided - if (title === null) { + if (!title) { return; } - // @ts-ignore - getBoundingClientRect is not part of the d3 type definition - const rect = this.getBoundingClientRect(); + const rect = (event.currentTarget as Element).getBoundingClientRect(); tooltipElem.transition().duration(200).style('opacity', '.9'); tooltipElem - .text(el.attr('title')) - .style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px') - .style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px'); - tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '
')); + .html(title.replace(/<br\/>/g, '
')) + .style('left', `${window.scrollX + rect.left + rect.width / 2}px`) + .style('top', `${window.scrollY + rect.bottom + 4}px`); + el.classed('hover', true); }) .on('mouseout', (event: MouseEvent) => { tooltipElem.transition().duration(500).style('opacity', 0); - const el = select(event.currentTarget as HTMLElement); - el.classed('hover', false); + select(event.currentTarget as HTMLElement).classed('hover', false); }); }; diff --git a/packages/mermaid/src/diagrams/flowchart/flowDb.ts b/packages/mermaid/src/diagrams/flowchart/flowDb.ts index 632633730..d6ecc7142 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDb.ts +++ b/packages/mermaid/src/diagrams/flowchart/flowDb.ts @@ -611,6 +611,21 @@ You have to call mermaid.initialize.` const el = select(e.currentTarget as Element); el.classed('hover', false); }); + // @ts-ignore TODO: fix this + tooltipElem = select('body') + .append('div') + .attr('class', 'mermaidTooltip') + .style('opacity', 0) + .style('position', 'absolute') + .style('text-align', 'center') + .style('max-width', '200px') + .style('padding', '2px') + .style('font-size', '12px') + .style('background', '#ffffde') + .style('border', '1px solid #333') + .style('border-radius', '2px') + .style('pointer-events', 'none') + .style('z-index', '100'); } /**