简体   繁体   中英

How to prevent tooltip going out of screen reactjs

Here a small demo. There are a few block; hovering on each block appears a tooltip(orange rect). It doesn't work correctly.

Tooltip should be displayed from left or right side. To get sizes of tooltip need to display it. Coords to display tooltip can be calculated only after tooltip is displayed

Codesandbox https://codesandbox.io/s/react-ref-65jj6?file=/src/index.js:88-231

 const { useState, useEffect, useCallback } = React; function App() { return ( <div> <HoveredBlock index={1} /> <HoveredBlock index={2} blockStyle={{ marginLeft: "5%" }} /> <HoveredBlock index={3} blockStyle={{ marginLeft: "50%" }} /> </div> ); } function calcCoords(blockRect, hoverRect) { const docWidth = document.documentElement.clientWidth; const isLeft = blockRect.right + hoverRect.width > docWidth; const coords = {}; if (!isLeft) { coords.x = blockRect.right; coords.y = blockRect.top; coords.type = "right"; } else { coords.x = blockRect.left - 5 - hoverRect.width; coords.y = blockRect.top; coords.type = "left"; } return coords; } function HoveredBlock({ index, blockStyle }) { const [blockRect, setBlockRect] = useState(); const [hoverRect, setHoverRect] = useState(); const [showHover, setShowHover] = useState(false); const [coords, setCoords] = useState(); const blockRef = useCallback((node) => { if (node) { setBlockRect(node.getBoundingClientRect()); } }, []); const hoverRef = useCallback( (node) => { if (showHover && node) { setHoverRect(node.getBoundingClientRect()); } }, [showHover] ); useEffect(() => { if (showHover && hoverRect) { const coords = calcCoords(blockRect, hoverRect); setCoords(coords); } }, [hoverRect]); const isHidden = !showHover || !coords ? 'hidden' : ''; return ( <div> <div ref={blockRef} className="block" style={blockStyle} onMouseEnter={() => setShowHover(true)} onMouseLeave={() => setShowHover(false)} > {index} </div> <div ref={hoverRef} className={'hover-block' + isHidden} style={{ left: coords && coords.x, top: coords && coords.y }} /> </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, rootElement );
 .block { width: 100px; height: 100px; background-color: aquamarine; margin-left: 82%; } .hover-block { position: fixed; width: 100px; height: 100px; background-color: coral; } .hidden { display: none; }
 <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script> <div id="root"></div>

I solved it. I changed the way how to hide element: visibility:hidded instead of display:none

export default function HoveredBlock({ blockStyle }) {
  const [blockRect, setBlockRect] = useState();
  const [hoverRect, setHoverRect] = useState();
  const [showHover, setShowHover] = useState(false);

  const [coords, setCoords] = useState();

  const blockRef = useCallback((node) => {
    if (node) {
      setBlockRect(node.getBoundingClientRect());
    }
  }, []);

  const hoverRef = useCallback((node) => {
    if (node) {
      setHoverRect(node.getBoundingClientRect());
    }
  }, []);

  useEffect(() => {
    if (showHover) {
      console.log({ blockRect, hoverRect });
      const coords = calcCoords(blockRect, hoverRect);

      setCoords(coords);
    }
  }, [showHover, blockRect, hoverRect]);

  return (
    <>
      <div
        ref={blockRef}
        className="block"
        style={blockStyle}
        onMouseEnter={() => setShowHover(true)}
        onMouseLeave={() => setShowHover(false)}
      />
      <div
        ref={hoverRef}
        className={cx("hover-block", {
          hidden: !showHover || !coords
        })}
        style={{
          left: coords && coords.x,
          top: coords && coords.y
        }}
      ></div>
    </>
  );
}
.block {
  width: 100px;
  height: 100px;
  background-color: aquamarine;
  margin-left: 20%;
}

.hover-block {
  position: fixed;
  width: 100px;
  height: 100px;
  background-color: coral;
}

.hidden {
  visibility: hidden;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM