Skip to content

[FEAT REQ] setClose or close method #1036

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sovetski opened this issue May 29, 2023 · 7 comments · Fixed by #1109
Closed

[FEAT REQ] setClose or close method #1036

sovetski opened this issue May 29, 2023 · 7 comments · Fixed by #1109
Labels
Feature Request V6 It might get fixed/merged before, but most likely only on V6's release.

Comments

@sovetski
Copy link

Is your feature request related to a problem? Please describe.
I know that there is an option to make the tooltip "hidden", but it does not help in my case, once we set "hidden" to "true", it does not appear anymore. In some situation, we need to manage the hide/show manually, for example I am using this package: https://github.com/JedWatson/react-select and I need to manage it on my side, if not Tooltip will not work.

Describe the solution you'd like
What will be perfect, is to get a method like "close()" to be able to close the tooltip which will show again if we hover on the parent element. I saw that there is already a function named "handleShow", maybe you can just "export" it?

Describe alternatives you've considered

Additional context
If you make "handleShow" public, it should be fine, if not, adding "close()" and "show()" will be very useful.

@gabrieljablonski gabrieljablonski changed the title setClose or close method [FEAT REQ] setClose or close method May 29, 2023
@gabrieljablonski
Copy link
Member

gabrieljablonski commented May 29, 2023

The easiest way to expose a function such as handleShow() would require using a context provider, which is something we're trying to move away from.

The other alternative is exposing a ref prop which we could use to expose this and possibly other functions with useImperativeHandle().

We're not planning on working on this right now, since it seems like a more unusual (although very valid) use-case, though I'll leave this open since it's still an interesting idea that we can work on in the future.


My suggestions for a workaround:

  1. Fully control the isOpen prop manually if you need some complex use-cases. Some examples from the docs.
  2. If what you need is simple enough, you could do something like in this example. If you have multiple tooltips, you can write a wrapper component with your custom logic.
import * as React from 'react';
import { Tooltip } from 'react-tooltip';

export default function App() {
  const [hidden, setHidden] = React.useState(false);

  return (
    <div>
      <button
        data-tooltip-id="my-tooltip"
        data-tooltip-content="Hello World!"
        // can be used instead of `hidden` prop
        // data-tooltip-hidden={hidden}
        onClick={() => setHidden(true)}
        onMouseLeave={() => setHidden(false)}
      >
        click me!
      </button>
      <Tooltip id="my-tooltip" hidden={hidden} />
    </div>
  );
}

@github-actions
Copy link

This issue is stale because it has not seen activity in 30 days. Remove the stale label or comment within 14 days, or it will be closed.

@github-actions github-actions bot added the Stale This has not seen activity in quite some time label Aug 28, 2023
@gabrieljablonski gabrieljablonski added V6 It might get fixed/merged before, but most likely only on V6's release. and removed Stale This has not seen activity in quite some time labels Aug 28, 2023
@r3wt
Copy link

r3wt commented Oct 8, 2023

We're not planning on working on this right now, since it seems like a more unusual (although very valid) use-case

why on earth should people not wanting to use controlled state for tooltips in the year 2023 be an "unusual" use case. its a significant factor that lead me to choose your library to begin with. that, along with single anchor element, and html content support were my reasons for choosing your lib. the notion that exporting a close function from your package is some forbidden anti pattern is ridiculous. i beg you to reconsider this.

@gabrieljablonski
Copy link
Member

gabrieljablonski commented Oct 8, 2023

the notion that exporting a close function from your package is some forbidden anti pattern is ridiculous

At no point I said this would be a "forbidden antipattern" (quite the contrary in fact). If so, this issue would've been closed long ago as "not planned".

This is not as trivial as "exporting a close function" (trust me, I've tried). Due to internal design, it would require a few intricate changes for this feature to work without bugs.

why on earth should people not wanting to use controlled state for tooltips in the year 2023 be an "unusual" use case

In my experience in maintaining this package for almost a year, most (I'd easily say 90%+) of use-cases I've seen involve using the tooltip (at least functionally) with mostly default options. Most people just need a quick and easy way to show stuff when hovering an element, and that's about it. Rarely have we had to suggest workarounds (such as in my comment above) to features not yet available.

We appreciate your input, and we will implement this (again, the issue would've been closed already otherwise). But unfortunately, this would take a bit more time than we have available to dedicate to this project right now.

@r3wt
Copy link

r3wt commented Oct 9, 2023

@sovetski did you find a work around, if not, i will share my somewhat poor solution here. track the focus state using focusin/focusout, and then use it to toggle a class on the wrapper which will hide the tooltips with css.

const useShouldHideTooltip = () => {
  const [hidden,setHidden] = useState(false);
  
  const handleFocus = () => {
    // if the active element has `data-tooltip-id`, we know it is a tooltip trigger
    setHidden(!!(document.activeElement as HTMLElement)?.dataset?.tooltipId);
  }
  
  useEffect(() => {
    document.addEventListener('focusin', handleFocus)
    document.addEventListener('focusout',handleFocus)
    return () => {
      document.removeEventListener('focusin', handleFocus);
      document.removeEventListener('focusout', handleFocus);
    };
  }, [])
  
  return hidden;
}

function App() {
  console.log('App.render');
  const tooltipHidden = useShouldHideTooltip();
  return (
    <div className={classNames("react-tooltip-watchdog",tooltipHidden&&'active')}>
      <Tooltip id="tooltip1" place="bottom" delayShow={200} />
    </div>
    ...
  );
}  
.react-tooltip-watchdog.active .react-tooltip {
  opacity: 0 !important;
  display: none !important;
  visibility: hidden !important;
}

this doesn't seem to be very reliable . I made some changes, so now if user clicks away from focused element, but something other than body is focused, so long as its not a tooltip trigger, tooltips will be visible again. this is working good for my use case. note, if you want to make use of it with tooltips triggered by click, need to add further checks on the data- attritubes to suit your use case

@gabrieljablonski
Copy link
Member

gabrieljablonski commented Oct 31, 2023

@sovetski It's been quite a while, but if you'd like to try out the beta version [email protected], we now expose open() and close() methods (and some other stuff).

Still doing some testing and no documentation yet, but it should be merged soon.

See the changes on the PR for some info on how to use it, but you just need to create the ref and use it.

const tooltipRef = React.useRef<TooltipRefProps>(null)

tooltipRef.current?.open()
tooltipRef.current?.close()

<Tooltip ref={tooltipRef} />
interface TooltipImperativeOpenOptions {
  anchorSelect?: string
  position?: IPosition
  place?: PlacesType
  /**
   * In practice, `ChildrenType` -> `React.ReactNode`
   */
  content?: ChildrenType
  /**
   * Delay (in ms) before opening the tooltip.
   */
  delay?: number
}

interface TooltipImperativeCloseOptions {
  /**
   * Delay (in ms) before closing the tooltip.
   */
  delay?: number
}

interface TooltipRefProps {
  open: (options?: TooltipImperativeOpenOptions) => void
  close: (options?: TooltipImperativeCloseOptions) => void
  /**
   * @readonly
   */
  activeAnchor: HTMLElement | null
  /**
   * @readonly
   */
  place: PlacesType
  /**
   * @readonly
   */
  isOpen: boolean
}

@gabrieljablonski
Copy link
Member

gabrieljablonski commented Nov 13, 2023

After quite some time, [email protected] implements this feature (check the docs for details).

@sovetski thanks for the original suggestion, and feel free to make many more!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Request V6 It might get fixed/merged before, but most likely only on V6's release.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants