everweij / react-laag

Hooks to build things like tooltips, dropdown menu's and popovers in React
https://www.react-laag.com
MIT License
906 stars 44 forks source link

How to have permanently visible tooltip based on state... #52

Closed AJTJ closed 3 years ago

AJTJ commented 3 years ago

I'm sure I'm missing something, but I'm having a hard time finding out how to set my tooltips permanently open/visible based on some state value I send them, and not dependent on hovering.

Thanks in advance.

everweij commented 3 years ago

Hi @AJTJ, Today I released version v2.0.0, I think the should api / docs be a lot clearer now regarding this topic. In the new version the hook is controlled by default, meaning you have to supply an isOpen option to the useLayer hook:

const [isOpen, setOpen] = React.useState(false);
const {} = useLayer({ isOpen });

Let me know if this answers your question!

AJTJ commented 3 years ago

Seems like a great time to find your library! Perhaps it should be obvious, but if I'm setting isOpen: true, I'm getting errors that seem like it is trying to render the layer before it exists. Should I be confirming the layer exists somewhere before setting isOpen to true?

Error: react-laag: Could not find a valid reference for the layer element. There might be 2 causes:
   - Make sure that the 'ref' is set correctly on the layer element when isOpen: true. Also make sure your component forwards the ref with "forwardRef()".
   - Make sure that you are actually rendering the layer when the isOpen prop is set to true
addEventListeners

My code looks like this

import React from "react";
import { useLayer, useHover, Arrow } from "react-laag";

export const BasicTooltip = ({ children, toolTipCopy, showTip }) => {
  const [isOver, hoverProps] = useHover();

  const { triggerProps, layerProps, arrowProps, renderLayer } = useLayer({
    isOpen: true,
  });

  return (
    <>
      <span {...triggerProps} {...hoverProps}>
        {children}
      </span>
      {isOver &&
        renderLayer(
          <div className="tooltip" {...layerProps}>
            {toolTipCopy}
            <Arrow
              {...arrowProps}
              backgroundColor="#ff0000"
              borderWidth={1}
              borderColor="#000000"
              roundness={0.5}
            />
          </div>
        )}
    </>
  );
};
AJTJ commented 3 years ago

figured it out, this seems to solve it

import React from "react";
import { useLayer, useHover, Arrow } from "react-laag";

export const BasicTooltip = ({ children, toolTipCopy, showTip }) => {
  const [isOver, hoverProps] = useHover();

  const { triggerProps, layerProps, arrowProps, renderLayer } = useLayer({
    isOpen: showTip || isOver,
  });

  return (
    <>
      <span {...triggerProps} {...hoverProps}>
        {children}
      </span>
      {(showTip || isOver) &&
        renderLayer(
          <div className="tooltip" {...layerProps}>
            {toolTipCopy}
            <Arrow
              {...arrowProps}
              backgroundColor="#ff0000"
              borderWidth={1}
              borderColor="#000000"
              roundness={0.5}
            />
          </div>
        )}
    </>
  );
};
AJTJ commented 3 years ago

not sure why tho

everweij commented 3 years ago

@AJTJ , yes your last code-snippet is the way to go! 👍🏼

The important part is that when isOpen is set to true inside useLayer, react-laag expects to find the layer to be rendered somewhere in the DOM, and will throw an error otherwise.

So, it's important that isOpen inside useLayer matches your conditional inside your jsx-return block.

I hope this answers your question.

AJTJ commented 3 years ago

Really appreciate it Erik. This tool fits my needs precisely, since I am building a mock online banking portal for an NGO to teach financial literacy skills. I’ll send you the link once the project is complete.

On Dec 16, 2020, at 7:32 AM, Erik Verweij notifications@github.com wrote:

@AJTJ https://github.com/AJTJ , yes your last code-snippet is the way to go! 👍🏼

The important part is that when isOpen is set to true inside useLayer, react-laag expects to find the layer to be rendered somewhere in the DOM, and will throw an error otherwise.

So, it's important that isOpen inside useLayer matches your conditional inside your jsx-return block.

I hope this answers your question.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/everweij/react-laag/issues/52#issuecomment-746146753, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHEL2YFFZRGSAWSODHE54QDSVCLDBANCNFSM4UYTW72Q.

everweij commented 3 years ago

Glad to help :) Cool, interested in seeing what you're building with react-laag!