Skip to content

[FEAT REQ] Expose place context for use with multiple anchors #868

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
tonyketcham opened this issue Dec 20, 2022 · 6 comments
Closed

[FEAT REQ] Expose place context for use with multiple anchors #868

tonyketcham opened this issue Dec 20, 2022 · 6 comments

Comments

@tonyketcham
Copy link

tonyketcham commented Dec 20, 2022

Is your feature request related to a problem? Please describe.
I have customized the Tooltip arrow with a border and CSS mask which necessitates that the arrow is conditionally rotated based on the place that the arrow is rendered.

I tried adding a thin wrapper around the <TooltipProvider/> which stores + allows context consumers to set the place. Then in a component containing a customized TooltipWrapper, I attempt to set the place when it changes. This does not work, as many TooltipWrappers are mounted simultaneously with listeners for onMouseover which triggers the global tooltip instance to anchor onto the element within the hovered TooltipWrapper. So I then need to verbosely add state management to set the placement only of the currently hovered TooltipWrapper instance. This is essentially juggling alongside the internal state management of this library, which feels a bit hacky for my purposes.

Describe the solution you'd like
I would like to be able to use the internal useTooltip(), publicly exported in the dist, with the addition of activePlace to the TooltipContextData. Then I would easily be able to apply conditional Tailwind styles to the global tooltip instance based on:

/**
 * Global tooltip component that is rendered once at the root of the app, with dynamic content rendered into it by
 * `TooltipWrapper` instances.
 */
export const TooltipGlobal = function () {

  const { activePlace } = useTooltip();

  const arrowTransform = useMemo(() => {
    switch (activePlace) {
      case 'top':
        return 'rotate-[225deg]';

      case 'bottom':
        return 'rotate-45';

      case 'left':
        return '-rotate-45';

      case 'right':
        return 'rotate-[135deg]';

      default:
        throw new Error(`unhandled "activePlace" value: ${activePlace}`);
    }
  }, [placement]);

  return (
    <Tooltip
      classNameArrow={classNames(

        // bunch of custom styling here ...

        arrowTransform,
      )}
    />
  );
};
@gabrieljablonski
Copy link
Member

gabrieljablonski commented Dec 20, 2022

Exposing useTooltip() is something we're considering on eventually doing if the need ever arises, but for now we decided against it since it can be a bit confusing to use.

At first glance, and if I understand correctly, your use case seems to fall a bit out of the scope of the project. I can't think of many other use cases in which exposing internal tooltip data (such as activePlace) is beneficial, so I'm unsure about that.

I have customized the Tooltip arrow with a border and CSS mask which necessitates that the arrow is conditionally rotated based on the place that the arrow is rendered.

Something that is easy to do would be to give the tooltip arrow element different css classes according to the place value. Would that be enough for what you're trying to do? I'd appreciate if you could do some testing.

If useTooltip() turns out to be the only way to solve your problem (which I honestly doubt) we'll see what we can do.

@tonyketcham
Copy link
Author

tonyketcham commented Dec 20, 2022

Thanks for the quick reply! I agree that an alternative could be adding different css classes to the arrow according to the place value. I'd personally love to see that provided as a prop on <Tooltip/> similar to classNameArrow so I could provide my own classes inline, targeting those states.

Perhaps a prop named classNameArrowPlace which follows this structure:

<Tooltip
    classNameArrow={/* bunch of custom styling here ... */}
    classNameArrowPlace={
      top: 'rotate-[225deg]',
      bottom: 'rotate-45',
      left: '-rotate-45',
      right: 'rotate-[135deg]',
    }
  />

What do you think?

@tonyketcham
Copy link
Author

I'm happy to put together a PR for this -- just want to agree on the API first 👍

@gabrieljablonski
Copy link
Member

Go for it, that seems good enough.

I was actually considering the extra class name as something like ${classNameArrow}__${place}, but that might be a little too limiting.

Submit the PR as you've suggested and we'll go from there.

@danielbarion
Copy link
Member

danielbarion commented Dec 20, 2022

Hi guys,

instead of:

<Tooltip
    classNameArrow={/* bunch of custom styling here ... */}
    classNameArrowPlace={
      top: 'rotate-[225deg]',
      bottom: 'rotate-45',
      left: '-rotate-45',
      right: 'rotate-[135deg]',
    }
  />

why not:

// https://www.npmjs.com/package/classnames
import classNames from 'classnames'


...
const [place, setPlace] = useState('top')
...


<Tooltip
    classNameArrow={classNames(/* bunch of custom styling here ... */, {
       'rotate-[225deg]': place === 'top',
       'rotate-45': place === 'bottom',
       '-rotate-45': place === 'left',
       'rotate-[135deg]': place === 'right',
    )}
  />

Why not use classnames package to handle these conditional CSS classes?

@gabrieljablonski
Copy link
Member

It seems like manually keeping track of place and using classnames would solve this problem.

If it doesn't, feel free to reopen the issue so we can discuss other alternatives.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants