@donkit-ai/design-system 0.3.4 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/Tooltip.jsx +61 -51
package/package.json
CHANGED
|
@@ -16,37 +16,42 @@ export function Tooltip({
|
|
|
16
16
|
|
|
17
17
|
useEffect(() => {
|
|
18
18
|
if (isVisible && !position && wrapperRef.current && tooltipRef.current) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
else
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
19
|
+
// Wait for browser to render the tooltip before measuring
|
|
20
|
+
requestAnimationFrame(() => {
|
|
21
|
+
if (!wrapperRef.current || !tooltipRef.current) return;
|
|
22
|
+
|
|
23
|
+
const wrapperRect = wrapperRef.current.getBoundingClientRect();
|
|
24
|
+
const tooltipRect = tooltipRef.current.getBoundingClientRect();
|
|
25
|
+
const viewportHeight = window.innerHeight;
|
|
26
|
+
const viewportWidth = window.innerWidth;
|
|
27
|
+
|
|
28
|
+
// Calculate available space in each direction
|
|
29
|
+
const spaceTop = wrapperRect.top;
|
|
30
|
+
const spaceBottom = viewportHeight - wrapperRect.bottom;
|
|
31
|
+
const spaceLeft = wrapperRect.left;
|
|
32
|
+
const spaceRight = viewportWidth - wrapperRect.right;
|
|
33
|
+
|
|
34
|
+
const tooltipHeight = tooltipRect.height;
|
|
35
|
+
const tooltipWidth = tooltipRect.width;
|
|
36
|
+
|
|
37
|
+
// Prefer top/bottom first, then left/right
|
|
38
|
+
if (spaceTop >= tooltipHeight + 8) {
|
|
39
|
+
setComputedPosition('top');
|
|
40
|
+
} else if (spaceBottom >= tooltipHeight + 8) {
|
|
41
|
+
setComputedPosition('bottom');
|
|
42
|
+
} else if (spaceRight >= tooltipWidth + 8) {
|
|
43
|
+
setComputedPosition('right');
|
|
44
|
+
} else if (spaceLeft >= tooltipWidth + 8) {
|
|
45
|
+
setComputedPosition('left');
|
|
46
|
+
} else {
|
|
47
|
+
// Fallback to direction with most space
|
|
48
|
+
const maxSpace = Math.max(spaceTop, spaceBottom, spaceLeft, spaceRight);
|
|
49
|
+
if (maxSpace === spaceTop) setComputedPosition('top');
|
|
50
|
+
else if (maxSpace === spaceBottom) setComputedPosition('bottom');
|
|
51
|
+
else if (maxSpace === spaceRight) setComputedPosition('right');
|
|
52
|
+
else setComputedPosition('left');
|
|
53
|
+
}
|
|
54
|
+
});
|
|
50
55
|
} else if (position) {
|
|
51
56
|
setComputedPosition(position);
|
|
52
57
|
}
|
|
@@ -55,28 +60,33 @@ export function Tooltip({
|
|
|
55
60
|
// Check viewport boundaries and adjust position
|
|
56
61
|
useEffect(() => {
|
|
57
62
|
if (isVisible && tooltipRef.current && wrapperRef.current) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
// Wait for browser to render the tooltip before measuring
|
|
64
|
+
requestAnimationFrame(() => {
|
|
65
|
+
if (!tooltipRef.current || !wrapperRef.current) return;
|
|
66
|
+
|
|
67
|
+
const tooltipRect = tooltipRef.current.getBoundingClientRect();
|
|
68
|
+
const viewportWidth = window.innerWidth;
|
|
69
|
+
const PADDING = 8; // minimum distance from viewport edge
|
|
70
|
+
|
|
71
|
+
let xOffset = 0;
|
|
72
|
+
let arrowShift = 0;
|
|
73
|
+
|
|
74
|
+
// For top/bottom positions, check horizontal overflow
|
|
75
|
+
if (computedPosition === 'top' || computedPosition === 'bottom') {
|
|
76
|
+
// Check if tooltip overflows on the right
|
|
77
|
+
if (tooltipRect.right > viewportWidth - PADDING) {
|
|
78
|
+
xOffset = viewportWidth - PADDING - tooltipRect.right;
|
|
79
|
+
arrowShift = -xOffset; // arrow moves opposite direction
|
|
80
|
+
}
|
|
81
|
+
// Check if tooltip overflows on the left
|
|
82
|
+
else if (tooltipRect.left < PADDING) {
|
|
83
|
+
xOffset = PADDING - tooltipRect.left;
|
|
84
|
+
arrowShift = -xOffset; // arrow moves opposite direction
|
|
85
|
+
}
|
|
71
86
|
}
|
|
72
|
-
// Check if tooltip overflows on the left
|
|
73
|
-
else if (tooltipRect.left < PADDING) {
|
|
74
|
-
xOffset = PADDING - tooltipRect.left;
|
|
75
|
-
arrowShift = -xOffset; // arrow moves opposite direction
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
87
|
|
|
79
|
-
|
|
88
|
+
setOffset({ x: xOffset, arrowOffset: arrowShift });
|
|
89
|
+
});
|
|
80
90
|
} else {
|
|
81
91
|
setOffset({ x: 0, arrowOffset: 0 });
|
|
82
92
|
}
|