|
1 |
| -import { computePosition, flip, offset, shift } from '@floating-ui/dom'; |
2 |
| -import { CSSProperties, useEffect, useRef, useState } from 'react'; |
| 1 | +import { CSSProperties, useState } from 'react'; |
3 | 2 | import styled from 'styled-components';
|
4 | 3 | import { spacing } from '../../spacing';
|
5 | 4 | import { fontSize, zIndex } from '../../style/theme';
|
6 | 5 | import { getThemePropSelector } from '../../utils';
|
| 6 | +import { useFloating, useHover, useInteractions } from '@floating-ui/react'; |
7 | 7 | export const TOP = 'top';
|
8 | 8 | export const BOTTOM = 'bottom';
|
9 | 9 | export const LEFT = 'left';
|
@@ -40,11 +40,9 @@ const TooltipContainer = styled.div`
|
40 | 40 | display: inline-block;
|
41 | 41 | `;
|
42 | 42 | const TooltipOverLayContainer = styled.div<{
|
43 |
| - placement: Position; |
44 | 43 | style?: CSSProperties;
|
45 | 44 | }>`
|
46 | 45 | display: inline-block;
|
47 |
| - opacity: 0; |
48 | 46 | position: fixed;
|
49 | 47 | width: max-content;
|
50 | 48 | border: 1px solid ${getThemePropSelector('border')};
|
@@ -85,51 +83,41 @@ function Tooltip({
|
85 | 83 | overlay,
|
86 | 84 | ...rest
|
87 | 85 | }: Props) {
|
88 |
| - const childrenRef = useRef<HTMLDivElement | null>(null); |
89 |
| - const tooltipRef = useRef<HTMLDivElement | null>(null); |
90 |
| - |
91 | 86 | const [isTooltipVisible, setIsTooltipVisible] = useState(false);
|
92 |
| - useEffect(() => { |
93 |
| - if (childrenRef.current && tooltipRef.current) { |
94 |
| - computePosition(childrenRef.current, tooltipRef.current, { |
95 |
| - placement, |
96 |
| - middleware: [offset(5), shift(), flip()], |
97 |
| - }).then(({ x, y }) => { |
98 |
| - if (tooltipRef.current) { |
99 |
| - Object.assign(tooltipRef.current.style, { |
100 |
| - opacity: '1', |
101 |
| - // we set opacity to 1 to make sure the tooltip is not displayed before the position is computed |
102 |
| - left: `${x}px`, |
103 |
| - top: `${y}px`, |
104 |
| - }); |
105 |
| - } |
106 |
| - }); |
107 |
| - } |
108 |
| - }, [tooltipRef.current, childrenRef.current, isTooltipVisible]); |
| 87 | + |
| 88 | + const { refs, floatingStyles, context } = useFloating({ |
| 89 | + open: isTooltipVisible, |
| 90 | + onOpenChange: setIsTooltipVisible, |
| 91 | + placement: placement, |
| 92 | + }); |
| 93 | + |
| 94 | + const hover = useHover(context); |
| 95 | + |
| 96 | + const { getReferenceProps, getFloatingProps } = useInteractions([hover]); |
109 | 97 | return (
|
110 |
| - <TooltipContainer |
111 |
| - className="sc-tooltip" |
112 |
| - onPointerEnter={() => { |
113 |
| - setIsTooltipVisible(true); |
114 |
| - }} |
115 |
| - onPointerLeave={() => { |
116 |
| - setIsTooltipVisible(false); |
117 |
| - }} |
118 |
| - > |
119 |
| - {isTooltipVisible && overlay ? ( |
120 |
| - <TooltipOverLayContainer |
121 |
| - ref={tooltipRef} |
122 |
| - className="sc-tooltip-overlay" |
123 |
| - placement={placement} |
| 98 | + <> |
| 99 | + <TooltipContainer className="sc-tooltip"> |
| 100 | + {isTooltipVisible && overlay ? ( |
| 101 | + <TooltipOverLayContainer |
| 102 | + className="sc-tooltip-overlay" |
| 103 | + ref={refs.setFloating} |
| 104 | + style={floatingStyles} |
| 105 | + {...getFloatingProps()} |
| 106 | + > |
| 107 | + <TooltipText className="sc-tooltip-overlay-text"> |
| 108 | + {overlay} |
| 109 | + </TooltipText> |
| 110 | + </TooltipOverLayContainer> |
| 111 | + ) : null} |
| 112 | + <div |
124 | 113 | style={overlayStyle}
|
| 114 | + ref={refs.setReference} |
| 115 | + {...getReferenceProps()} |
125 | 116 | >
|
126 |
| - <TooltipText className="sc-tooltip-overlay-text"> |
127 |
| - {overlay} |
128 |
| - </TooltipText> |
129 |
| - </TooltipOverLayContainer> |
130 |
| - ) : null} |
131 |
| - <div ref={childrenRef}>{children}</div> |
132 |
| - </TooltipContainer> |
| 117 | + {children} |
| 118 | + </div> |
| 119 | + </TooltipContainer> |
| 120 | + </> |
133 | 121 | );
|
134 | 122 | }
|
135 | 123 |
|
|
0 commit comments