Skip to content
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

Nested tooltips don't function as intended #2193

Closed
Nantris opened this issue Aug 21, 2022 · 11 comments
Closed

Nested tooltips don't function as intended #2193

Nantris opened this issue Aug 21, 2022 · 11 comments
Labels
help wanted Contributions from community are welcome

Comments

@Nantris
Copy link
Contributor

Nantris commented Aug 21, 2022

What package has an issue

@mantine/core

Describe the bug

Nested tooltips seem to inherit each-others properties leading to buggy behaviors or not showing at all.

See the linked demo where we attempt to nest a clickable Tooltip inside of a hoverable Tooltip, and instead neither fires.

What version of @mantine/hooks page do you have in package.json?

5.2.0

If possible, please include a link to a codesandbox with the reproduced problem

https://codesandbox.io/s/optimistic-meadow-95x4i9

Do you know how to fix the issue

No

Are you willing to participate in fixing this issue and create a pull request with the fix

Yes

Possible fix

Unknown. It works with TippyJS, however they manage this.

We had a custom wrapper to also help with this, but that doesn't help in this case either unfortunately:

function mergeRefs(refs) {
  return value => {
    refs.forEach(ref => {
      if (typeof ref === 'function') {
        ref(value);
      } else if (ref != null) {
        ref.current = value;
      }
    });
  };
}


const TooltipWrap = forwardRef(({ label, tooltipOpts = {}, children }, ref) => {
  const mergedRefs = mergeRefs([children.ref, ref]);
  return label ? (
    <Tooltip
      {...{
        label,
        // NOTE: Doesn't work even if we use ...props here
      }}
      {...tooltipOpts}
    >
      {React.cloneElement(children, { ref: mergedRefs })}
    </Tooltip>
  ) : (
    React.cloneElement(children, { ref: mergedRefs })
  );
});
@Nantris
Copy link
Contributor Author

Nantris commented Aug 22, 2022

@rtivital could you comment on whether should nested tooltips work or should we back out of transitioning to Mantine's tooltips?

I assume they should work since you removed "review required"?

@rtivital
Copy link
Member

Yes, I will try to resolve this, not sure if it is possible yet

@Nantris
Copy link
Contributor Author

Nantris commented Aug 27, 2022

My example presumed that focus would fire in response to click events, which was mistaken. Here's an updated repro

https://codesandbox.io/s/inspiring-snow-zh1y16?file=/src/App.tsx

Note that the nested tooltips can work if the top level tooltip is a controlled component. I wonder if that might help point to a fix for nested use cases.

@rtivital rtivital added the help wanted Contributions from community are welcome label Oct 1, 2022
@nfbuckley
Copy link
Contributor

As a work around, if you wrap the inner ToolTip in a non fragment component (such as <Box> or <div>) it seems to work:

https://codesandbox.io/s/infallible-nash-edf3f2?file=/src/App.tsx

This makes some sense, as the Tooltip needs an immediate child element that it can reference. One approach would be to automatically wrap the children in a component if an inner Tooltip is detected as the direct child.

@rtivital If this an approach you approve of I could put together a PR.

@Nantris
Copy link
Contributor Author

Nantris commented Oct 20, 2022

I don't think an interceding element is a good solution as it can affect styling. It should theoretically be possible with just forwardRef and no extra elements, I think?

@nfbuckley
Copy link
Contributor

Using forwardRef gets a bit tricky as the ToolTip actually needs to be rendered, in this case as an <OptionalPortal>. One could do the equivalent and avoid another element by flattening the nested tooltip(s) and creating all the necessary '`s against the one child component. The last complication is you'd have to also merge the tooltip events in the child component as well. It all seems doable, but perhaps needlessly complicated. I could try implementing it to see if it works.

Question: does the work around get you what you need? I understand there are some concerns with styling, but if you use an inner container without any style (such as <Box>) then the side effects seem manageable.

@nfbuckley
Copy link
Contributor

Never mind my previous comment - there is a simpler solution which involves merging the incoming events (from the parent tooltip) with the current tooltip. I did a quick test and it appears to work. I'll see if I can't put together a PR.

@Nantris
Copy link
Contributor Author

Nantris commented Oct 25, 2022

Damn, fixed before I even got to reply! Thanks a ton @nfbuckley!

This issue is closed by #2768.

@Nantris Nantris closed this as completed Oct 25, 2022
@Nantris
Copy link
Contributor Author

Nantris commented Dec 17, 2022

@nfbuckley @rtivital I figured I could remove our span around our inner tooltips now, but when I did, the inner tooltip now appears in a totally unexpected location (upper-left corner of the screen.) It only occurs when using withinPortal.

I thought maybe because we defined defaultProps for Portal through MantineProvider, but when I remove that - no difference.

So far, I'm not sure how to reproduce this in a sandbox though, I guess it's not particularly easy to instigate. Any ideas?

image

Edit:

Actually, removing the span seems to break positioning even without withinPortal, albeit very minorly, by 10ish pixels, rather than moving it across the entire screen.

@rtivital
Copy link
Member

Provide a sandbox that reproduces the issue

@Nantris
Copy link
Contributor Author

Nantris commented Dec 19, 2022

@rtivital I've tried to reproduce it and I'll continue to try. I'm asking if you have any ideas what CSS properties or patterns might be relevant to the portaled tooltip losing its positioning?

So far, I'm not sure how to reproduce this in a sandbox though, I guess it's not particularly easy to instigate. Any ideas?

For example, I can get the positioning screwed up using absolute positioning on the child - but this appears to be a separate oddity that doesn't move the tooltip to the zero-point of its portal. I say "separate" because in our actual code nothing is absolute positioned, and the outcome here is a bit different.

I've played with a number of properties but haven't been able to reproduce quite what we're seeing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Contributions from community are welcome
Projects
None yet
Development

No branches or pull requests

3 participants