aboutsummaryrefslogtreecommitdiff
path: root/src/lib/Tooltip/tooltip.ts
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-04-19 11:04:12 +0000
committerFuwn <[email protected]>2026-04-19 11:04:12 +0000
commit28860bb88da4c08e3ba383adc9c23ae3689310b6 (patch)
tree4bffd765ca23d412b2065179f4e60993b824ca1a /src/lib/Tooltip/tooltip.ts
parentRevert "fix(tooltip): park measurement node off-screen to stop body resize" (diff)
downloaddue.moe-28860bb88da4c08e3ba383adc9c23ae3689310b6.tar.xz
due.moe-28860bb88da4c08e3ba383adc9c23ae3689310b6.zip
fix(tooltip): use fixed positioning and snappy cursor tracking
Body grew on hover because the absolutely-positioned tooltip was appended to document.body without top/left, so its static-flow position extended body.scrollWidth/scrollHeight during layout measurement. Switch both the use:tooltip directive and LinkedTooltip's measurement div to position:fixed, which is relative to the viewport and does not contribute to the body's scroll area. The directive now also uses clientX/clientY (dropping the scrollY offset for the pin branch), removes the 100ms mousemove debounce, and drops the top/left transition so the tooltip tracks the cursor without feeling laggy or sliding in from the page top.
Diffstat (limited to 'src/lib/Tooltip/tooltip.ts')
-rw-r--r--src/lib/Tooltip/tooltip.ts22
1 files changed, 8 insertions, 14 deletions
diff --git a/src/lib/Tooltip/tooltip.ts b/src/lib/Tooltip/tooltip.ts
index 5772c33f..8c846a78 100644
--- a/src/lib/Tooltip/tooltip.ts
+++ b/src/lib/Tooltip/tooltip.ts
@@ -3,9 +3,7 @@ const tooltip = (element: HTMLElement) => {
const offset = 10;
const tooltipTransitionTime = 200;
const tooltipHideDelay = 10;
- const debounceDelay = 100;
let hideTimeout: number | null = null;
- let debounceTimer: number | null = null;
if (element.dataset.tooltipDisable === "true") return;
@@ -13,13 +11,14 @@ const tooltip = (element: HTMLElement) => {
if (!tooltipDiv) {
tooltipDiv = document.createElement("div");
- tooltipDiv.style.position = "absolute";
+ tooltipDiv.style.position = "fixed";
+ tooltipDiv.style.top = "-9999px";
+ tooltipDiv.style.left = "-9999px";
tooltipDiv.style.zIndex = "1000";
tooltipDiv.style.opacity = "0";
- tooltipDiv.style.transition = `opacity ${tooltipTransitionTime}ms ease-in-out, top 0.3s ease, left 0.3s ease`;
+ tooltipDiv.style.transition = `opacity ${tooltipTransitionTime}ms ease-in-out`;
tooltipDiv.style.pointerEvents = "none";
tooltipDiv.style.whiteSpace = "nowrap";
- tooltipDiv.style.zIndex = "1000";
tooltipDiv.classList.add("card");
tooltipDiv.classList.add("card-small");
@@ -47,7 +46,7 @@ const tooltip = (element: HTMLElement) => {
if (top < 0) top = rect.top + rect.height + offset;
tooltipDiv.style.left = `${left}px`;
- tooltipDiv.style.top = `${top + window.scrollY}px`;
+ tooltipDiv.style.top = `${top}px`;
return;
}
@@ -116,18 +115,14 @@ const tooltip = (element: HTMLElement) => {
}
if (!tooltipDiv) {
- showTooltip(title, event.pageX, event.pageY);
+ showTooltip(title, event.clientX, event.clientY);
}
}
};
const handleMouseMove = (event: MouseEvent) => {
- if (debounceTimer !== null) clearTimeout(debounceTimer);
-
- debounceTimer = window.setTimeout(() => {
- if (tooltipDiv && tooltipDiv.style.opacity === "1")
- updateTooltipPosition(event.pageX, event.pageY);
- }, debounceDelay);
+ if (tooltipDiv && tooltipDiv.style.opacity === "1")
+ updateTooltipPosition(event.clientX, event.clientY);
};
const handleMouseLeave = () => {
@@ -149,7 +144,6 @@ const tooltip = (element: HTMLElement) => {
element.removeEventListener("mouseleave", handleMouseLeave);
if (hideTimeout !== null) clearTimeout(hideTimeout);
- if (debounceTimer !== null) clearTimeout(debounceTimer);
if (tooltipDiv && document.body.contains(tooltipDiv)) {
document.body.removeChild(tooltipDiv);