diff --git a/packages/frontend/src/components/graph/Graph.tsx b/packages/frontend/src/components/graph/Graph.tsx index 337a00a9..49e2ad97 100644 --- a/packages/frontend/src/components/graph/Graph.tsx +++ b/packages/frontend/src/components/graph/Graph.tsx @@ -6,6 +6,7 @@ import { QuizGitGraphCommit } from "../../types/quiz"; import fillColor from "./fillColor"; import { InitialDataProps, parsingMultipleParents } from "./parsing"; +import renderTooltip from "./renderTooltip"; const { grey500 } = color.$scale; @@ -87,6 +88,12 @@ function renderD3(svgRef: RefObject, data: InitialDataProps[]) { (exit) => exit.transition().duration(DURATION).style("opacity", 0).remove(), ) + .on("mouseover", (event, d) => { + const existingTooltip = svg.select("#tooltip"); + if (existingTooltip.empty()) { + renderTooltip(svg, d); + } + }) .attr("cx", (d) => d.x) .attr("cy", (d) => d.y) .attr("r", 13) diff --git a/packages/frontend/src/components/graph/renderTooltip.ts b/packages/frontend/src/components/graph/renderTooltip.ts index 5b5a859b..75eece69 100644 --- a/packages/frontend/src/components/graph/renderTooltip.ts +++ b/packages/frontend/src/components/graph/renderTooltip.ts @@ -79,5 +79,36 @@ export default function renderTooltip( .append("tspan") .attr("fill", color.$scale.grey700) .text((tooltipData: TooltipProps) => tooltipData.value) - .attr("id", (tooltipData: TooltipProps) => tooltipData.id); + .attr("id", (tooltipData: TooltipProps) => tooltipData.id) + .each(() => { + const currentValueNode: d3.Selection< + SVGTSpanElement | null, + unknown, + HTMLElement, + undefined + > = d3.select("#value"); + + if (!currentValueNode.empty() && currentValueNode.node()) { + const tspanMaxWidth = 110; + const originalText = currentValueNode.text(); + + let start = 0; + let end = tspanMaxWidth; + let mid; + while (start < end) { + mid = Math.floor((start + end) / 2); + const truncatedText = `${originalText.slice(0, mid)}...`; + currentValueNode.text(truncatedText); // Set text here for width calculation + const textWidth = + currentValueNode?.node()?.getComputedTextLength() || 0; + if (textWidth > tspanMaxWidth) { + end = mid; + } else { + start = mid + 1; + } + } + const truncatedText = `${originalText.slice(0, start - 1)}...`; + currentValueNode.text(truncatedText); + } + }); }