Skip to content

Commit 40439f0

Browse files
authored
fix(view): 스토리라인 차트 툴팁이 간헐적으로 나타나는 현상 해결 (#1005)
* fix: lint 에러 해결 * fix: 타이머 로직 정리 및 툴팁 상태 관리 추가 * refactor: 불필요한 상태 관리 제거
1 parent dec6749 commit 40439f0

File tree

2 files changed

+37
-11
lines changed

2 files changed

+37
-11
lines changed

packages/view/src/components/FolderActivityFlow/FolderActivityFlow.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import * as d3 from "d3";
22
import { useEffect, useRef, useMemo, useState } from "react";
33
import { useShallow } from "zustand/react/shallow";
44
import Breadcrumbs from "@mui/material/Breadcrumbs";
5-
import Link from "@mui/material/Link";
65
import Typography from "@mui/material/Typography";
76
import NavigateNextIcon from "@mui/icons-material/NavigateNext";
87
import WorkspacePremiumRoundedIcon from "@mui/icons-material/WorkspacePremiumRounded";
8+
import { Link } from "@mui/material";
99

1010
import { useDataStore } from "store";
1111

@@ -140,12 +140,9 @@ const FolderActivityFlow = () => {
140140
return;
141141
}
142142

143-
const svg = d3
144-
.select(svgRef.current)
145-
.attr("width", chartWidth)
146-
.attr("height", DIMENSIONS.height);
143+
const svg = d3.select(svgRef.current).attr("width", chartWidth).attr("height", DIMENSIONS.height);
147144

148-
//activity가 있는 폴더 카운트
145+
// activity가 있는 폴더 카운트
149146
const currentDepth = currentPath === "" ? 1 : currentPath.split("/").length + 1;
150147
const releaseContributorActivities = extractReleaseBasedContributorActivities(
151148
totalData,
@@ -200,9 +197,13 @@ const FolderActivityFlow = () => {
200197
return (
201198
<Link
202199
key={crumb}
200+
href={`#breadcrumb-${crumb}`}
203201
underline="none"
204-
component="button"
205-
onClick={() => navigateToBreadcrumb(index, breadcrumbs.length)}
202+
aria-label={`Navigate to ${crumb}`}
203+
onClick={(e) => {
204+
e.preventDefault();
205+
navigateToBreadcrumb(index, breadcrumbs.length);
206+
}}
206207
>
207208
{crumb}
208209
</Link>

packages/view/src/components/FolderActivityFlow/ReleaseVisualization.tsx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ export const renderReleaseVisualization = ({
4444
}: ReleaseVisualizationProps) => {
4545
const tooltip = d3.select(tooltipRef.current);
4646

47+
let tooltipShowTimer: ReturnType<typeof setTimeout> | null = null;
48+
let tooltipHideTimer: ReturnType<typeof setTimeout> | null = null;
49+
4750
// 스케일 설정
4851
const uniqueContributors = Array.from(new Set(releaseContributorActivities.map((a) => a.contributorName)));
4952
const uniqueReleases = Array.from(new Set(releaseContributorActivities.map((a) => a.releaseIndex))).sort(
@@ -184,6 +187,15 @@ export const renderReleaseVisualization = ({
184187
// 툴팁 이벤트
185188
dots
186189
.on("mouseover", function (event: MouseEvent, d: ReleaseContributorActivity) {
190+
if (tooltipHideTimer) {
191+
clearTimeout(tooltipHideTimer);
192+
tooltipHideTimer = null;
193+
}
194+
if (tooltipShowTimer) {
195+
clearTimeout(tooltipShowTimer);
196+
tooltipShowTimer = null;
197+
}
198+
187199
const currentRadius = sizeScale(d.changes);
188200
const hoveredRadius = currentRadius * 1.2;
189201

@@ -196,7 +208,9 @@ export const renderReleaseVisualization = ({
196208
const cy = parseFloat(nodeElement.getAttribute("cy") || "0");
197209

198210
// SVG 좌표를 화면 좌표로 변환
199-
const svgPoint = nodeElement.ownerSVGElement!.createSVGPoint();
211+
const ownerSvgElement = nodeElement.ownerSVGElement;
212+
if (!ownerSvgElement) return;
213+
const svgPoint = ownerSvgElement.createSVGPoint();
200214
svgPoint.x = cx;
201215
svgPoint.y = cy;
202216
const ctm = nodeElement.getScreenCTM();
@@ -224,20 +238,31 @@ export const renderReleaseVisualization = ({
224238
`);
225239

226240
// 페이드 인 애니메이션
227-
setTimeout(() => {
241+
tooltipShowTimer = setTimeout(() => {
228242
tooltip.style("opacity", "1");
243+
tooltipShowTimer = null;
229244
}, 10);
230245
})
231246
.on("mouseout", function (_event: MouseEvent, d: ReleaseContributorActivity) {
247+
if (tooltipShowTimer) {
248+
clearTimeout(tooltipShowTimer);
249+
tooltipShowTimer = null;
250+
}
251+
if (tooltipHideTimer) {
252+
clearTimeout(tooltipHideTimer);
253+
tooltipHideTimer = null;
254+
}
255+
232256
const currentRadius = sizeScale(d.changes);
233257

234258
// 노드 크기 원래대로
235259
d3.select(this).attr("r", currentRadius).attr("stroke-width", 0);
236260

237261
// 페이드 아웃 애니메이션
238262
tooltip.style("opacity", "0");
239-
setTimeout(() => {
263+
tooltipHideTimer = setTimeout(() => {
240264
tooltip.style("display", "none");
265+
tooltipHideTimer = null;
241266
}, 200);
242267
});
243268

0 commit comments

Comments
 (0)