react-tooltip icon indicating copy to clipboard operation
react-tooltip copied to clipboard

Multiple tooltip in same page open all at the same time

Open joedevgee opened this issue 6 years ago • 10 comments

I usually have multiple react-tooltip for each place I want to show a tooltip.

Problem, after clicking the second tooltip, the first tooltip does not close. Therefore, user is seeing both tooltip opening at the same time.

My assumption is that data-for and id is there to avoid this from happening

You can also see this demo on Edit 038px2yrmp

<a data-event="click" data-for="first-click" data-tip="firstClick">
   first tooltip
</a>
<ReactTooltip globalEventOff="click" id="first-click" />

<a data-event="click" data-for="second-click" data-tip="second-click">
  second tooltip
</a>
<ReactTooltip globalEventOff="click" id="second-click" />

I understand that a better way is to put only one reacttooltip for the whole app. But, is there any way to make multiple reacttooltip to work?

joedevgee avatar Apr 20 '18 17:04 joedevgee

Thank you for the working sample code and example code. This is obviously only a problem when using the data-event="click" activation - so one work-around is to use a hovering tool-tip. data-id is primarily used to connect a specific tooltip with a target, but I can see how it could help in this case. Do you think you might be able to look for a solution and submit a pull request?

aronhelser avatar Apr 28 '18 19:04 aronhelser

A potential work-around is to add an afterShow event handler and hide the other tooltips manually.

aronhelser avatar Apr 30 '18 17:04 aronhelser

@aronhelser Working on a major release now, will come back and raise a PR. Thanks for the solution

joedevgee avatar Apr 30 '18 17:04 joedevgee

@aronhelser can you explain more about this work-around ? how can you hide other tooltips after the show of some tooltip ?

guyazulay avatar Feb 04 '19 14:02 guyazulay

@joedevgee something new about this PR ?

guyazulay avatar Feb 04 '19 14:02 guyazulay

Not sure if that will fulfill your requirements, but if you reach this issue there is a chance that below workaround may come in handy:

const TooltipDemo = (props) => {
  const [isTooltipOpen, setTooltipOpen] = React.useState(false)
  const tooltipWrapperRef = React.useRef(null)

  const hideTooltipHandler = React.useCallback(() => {
    const tooltipWrapperEl = tooltipWrapperRef.current
    if (tooltipWrapperEl) {
      ReactTooltip.hide(tooltipWrapperEl)
      setTooltipOpen(false)
      document.removeEventListener("click", hideTooltipHandler)
    }
  }, [])

  const onTooltipTriggerClick = React.useCallback(() => {
    const tooltipWrapperEl = tooltipWrapperRef.current
    if (tooltipWrapperEl) {
      if (isTooltipOpen) {
        ReactTooltip.hide(tooltipWrapperEl)
        setTooltipOpen(false)
      } else {
        ReactTooltip.show(tooltipWrapperEl)
        setTooltipOpen(true)

        document.addEventListener("click", hideTooltipHandler)
      }
    }
  }, [isTooltipOpen])

  React.useEffect(() => {
    return () => {
      document.removeEventListener("click", hideTooltipHandler)
    }
  }, [])

  return (
    <section>
      <div
        data-tip
        data-for={props.id}
        ref={tooltipWrapperRef}
        data-event="click"
        data-event-off=""
        onClick={onTooltipTriggerClick}
      >
        /* your tooltip trigger here */
      </div>
      <ReactTooltip
        id={props.id}
        place="bottom"
        type="light"
        border
        isCapture
        effect="solid"
      >
        /* your tooltip content here */
      </ReactTooltip>
    </section>
  )
}

With multiple TooltipDemo components on one page the problem described by @joedevgee no longer occurs.

kkowalczuk avatar Jun 18 '19 06:06 kkowalczuk

@kkowalczuk do you mind doing your workaround using render props? I don't understand hooks that much yet

lestgabo avatar Sep 12 '19 09:09 lestgabo

you need to set data-event-off property data-event-off="mouseleave"

or you can combine with click if you need to work it on hover and click together data-event-off="mouseleave click"

nikolaySolodkiy avatar Mar 30 '20 08:03 nikolaySolodkiy

My workaround was to hide all tooltip with a onMouseEnter

<div
        data-tip
        data-for={props.id}
        onMouseEnter={()=>ReactTooltip.hide()}
      >
        /* your tooltip trigger here */
      </div>
      <ReactTooltip
        id={id}
        place="top"
        event="click"
        globalEventOff="click"
      >
        /* your tooltip content here */
      </ReactTooltip>

aurelien-gaillard avatar Sep 01 '21 08:09 aurelien-gaillard

i use onMouseDown to hide all tooltip

try it here : https://codesandbox.io/s/staging-feather-3q69z?file=/src/App.js

import "./styles.css";
import ReactTooltip from "react-tooltip";

const data = [
  {
    id: "1",
    label: "Image 1",
    link:
      "https://images.pexels.com/photos/10344201/pexels-photo-10344201.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"
  },
  {
    id: "2",
    label: "Image 2",
    link:
      "https://images.pexels.com/photos/10400270/pexels-photo-10400270.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"
  },
  {
    id: "3",
    label: "Image 3",
    link:
      "https://images.pexels.com/photos/2567854/pexels-photo-2567854.png?auto=compress&cs=tinysrgb&dpr=1&w=500"
  }
];

const wrapperStyle = {
  width: "200px",
  height: "200px",
  background: "#0971F1",
  marginTop: "100px"
};

const imageStyle = {
  width: "100%"
};

const TooltipDemo = (props) => {
  const stopDefault = (e) => {
    e.stopPropagation();
  };

  const hide = (e) => {
    ReactTooltip.hide();
  };

  return (
    <section>
      <a
        style={{
          cursor: "pointer"
        }}
        data-tip
        data-for={props.id}
        data-event="click"
        onMouseDown={hide}
      >
        {props.label}
      </a>

      <ReactTooltip
        id={props.id}
        place="right"
        effect="solid"
        clickable
        globalEventOff="click"
      >
        <div
          role="tab"
          onClick={stopDefault}
          onSelect={stopDefault}
          style={{
            width: "120px"
          }}
        >
          <img style={imageStyle} src={props.link} alt="" />
        </div>
      </ReactTooltip>
    </section>
  );
};

export default function App() {
  return (
    <div style={wrapperStyle}>
      {data.map((i) => {
        return (
          <TooltipDemo
            key={`tooltop${i.id}`}
            id={i.id}
            label={i.label}
            link={i.link}
          />
        );
      })}
    </div>
  );
}


oggnimodd avatar Dec 10 '21 06:12 oggnimodd