everweij / react-laag

Hooks to build things like tooltips, dropdown menu's and popovers in React

Home Page:https://www.react-laag.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[BUG] Tooltips are not closing when the hovering is too fast.

SalahAdDin opened this issue · comments

Describe the bug
We are using a tooltip on a table tool to show the user the dimensions of the table it is supposed to build; as the tool is a grid composed of many divs, the hovering is too fast and it seems the hook is unable to calculate the tooltip to close.

To Reproduce
Steps to reproduce the behavior:

  1. Create a grid of divs.
  2. Add a tooltip to every div.
  3. Go to the tool.
  4. Hover over the grid.
  5. Close the grid.
  6. Check the tooltips are still visible.

Expected behavior
It either:

  • should close the tooltip as soon as the element is not hovered anymore (the best).
  • should remove all the tooltips when the grid is not visible anymore.

Screenshots
tooltipsarenotdissapearing

Browser / OS (please complete the following information):

  • OS: Manjaro Linux x86_64
  • Browser: Firefox Browser
  • Version: 119

Additional context
The tooltip component is the following:

const isReactText = (children) =>
  ["string", "number"].includes(typeof children);

const Tooltip = ({
  text,
  component: Component,
  children,
  placement,
  className,
}) => {
  const [isOver, hoverProps, close] = useHover({
    hideOnScroll: true,
  });

  const { arrowProps, triggerProps, layerProps, renderLayer } = useLayer({
    isOpen: isOver,
    placement,
    triggerOffset: 4,
    auto: true,
    onDisappear: () => close(),
  });

  let trigger;

  if (isReactText(children)) {
    trigger = (
      <Component {...triggerProps} {...hoverProps}>
        {children}
      </Component>
    );
  } else {
    // In case of an react-element, we need to clone it in order to attach our own props
    trigger = React.cloneElement(children, {
      ...triggerProps,
      ...hoverProps,
    });
  }

  return (
    <>
      {trigger}
      {renderLayer(
        <AnimatePresence>
          {isOver && (
            <motion.span
              className={clsx("tooltip", className)}
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              transition={{ ease: [0.4, 0, 0.2, 1] }}
              {...layerProps}
            >
              {text}
              <Arrow {...arrowProps} size={8} roundness={0} />
            </motion.span>
          )}
        </AnimatePresence>
      )}
    </>
  );
};

Tooltip.defaultProps = {
  component: "div",
};

export default Tooltip;

And we are using it on the grid:

{Array.from(Array(state.rows)).map((row, rowIdx) =>
            Array.from(Array(state.cols)).map((col, colIdx) => (
              <Tooltip text={`${colIdx + 1}x${rowIdx + 1}`} placement="top">
                <div
                  className={clsx("tableBox__wrapper__items__item", {
                    "--selected":
                      rowIdx <= state.activeRow && colIdx <= state.activeCol,
                  })}
                  key={`col_${colIdx}_row_${rowIdx}`}
                  data-col={colIdx}
                  data-row={rowIdx}
                  onClick={addTable}
                />
              </Tooltip>
            ))
          )}