ycs77 / headlessui-float

Easily use Headless UI with Floating UI to position floating elements.
https://headlessui-float.vercel.app
MIT License
344 stars 11 forks source link

Add a prop to disable pointer events inside floating element #41

Closed VinceBT-BG closed 1 year ago

VinceBT-BG commented 1 year ago

Is your feature request related to a problem? Please describe. When using the component as a tooltip, you sometimes want to disable hovering completely but this issue happens: 2023-01-23 11 41 05 This is because there is no possibility to pass props to the wrapping div of the floating element

Describe the solution you'd like Either a prop disabling pointer events on the div, either being able to pass anything to the div, like a className or a style prop, that is added to it

ycs77 commented 1 year ago

Hi @VinceBT-BG, sorry I don't quite understand what you mean 😅, can you provide a simple example (like github repo, codesandbox, stackblitz...) to reproduce the above gif? (have your expectations and now actual)

VinceBT-BG commented 1 year ago

Sorry if I was unclear, my point was to add a way to pass custom style or classname to the floating container here https://github.com/ycs77/headlessui-float/blob/main/packages/react/src/float.tsx#L308, to pass for example pointer-events: none to completely ignore hover events and also add more possibility to customize

ycs77 commented 1 year ago

@VinceBT-BG can use floatingAs={React.Fragment} to have full floating element control:

import React from 'react'

<Float floatingAs={React.Fragment}>
  <Listbox.Button>
    ...
  </Listbox.Button>

  {/* now no <div> wrapper, you have full floating element control */}
  <Listbox.Options style="pointer-events: ...">
    ...
  </Listbox.Options>
</Float>

Does this solve your problem?

VinceBT-BG commented 1 year ago

The problem is that when I do that, the transition classnames are passed to the floating element, and all classnames that change transform property get overwritten by the translate, see screenshot

Capture d’écran 2023-02-03 à 17 20 10

I want to have scale-50 but the transform gets overwritten by translate in the DOM

ycs77 commented 1 year ago

Turn off transform to switch to top/left properties for positioning can solve:

<Float transform={false}>
VinceBT-BG commented 1 year ago
Capture d’écran 2023-02-03 à 18 18 05

Using that breaks some tooltips

VinceBT-BG commented 1 year ago
Capture d’écran 2023-02-03 à 18 18 51

This is how it renders without transform={false}

ycs77 commented 1 year ago

Or you can use custom forward element:

const FloatingWrapper = React.forwardRef(({ children, ...otherProps }, ref) => {
  // Add any your custom attributes or styles
  return <div {...otherProps} ref={ref}>{children}</div>
})

<Float floatingAs={FloatingWrapper}>
VinceBT-BG commented 1 year ago

With floatingAs={FloatingWrapper}

Capture d’écran 2023-02-06 à 12 09 43

2023-02-06 12 09 12

With just floatingAs="div" 2023-02-06 12 10 44

ycs77 commented 1 year ago

@VinceBT-BG If you want to make the tooltip I suggest using Tippy.js (Tippy.js for React: https://github.com/atomiks/tippyjs-react), I think the Headless UI Float is not to create the tooltip😅

But, if you still using Headless UI Float, can you provide your current tooltip code? I can be easy to debug.

ycs77 commented 1 year ago

Hi @VinceBT-BG, did your question get resolved? If so I will close this issue, please open a new one if you have any questions.

VinceBT-BG commented 1 year ago

I tried everything and did not manage to make it work, the simplest solution would be to add the basic possibility to forward style or classname to the element I provided

ycs77 commented 1 year ago

@VinceBT-BG I have added a feature to v0.11, you can add any attribute to the floating element at will, see Composable Mode, you can update to v0.11 and use it.

And here has a tooltip example:

import { useState } from 'react'
import { Float } from '@headlessui-float/react'

export default function ExampleTooltip() {
  const [show, setShow] = useState(false)
  return (
    <Float
      show={show}
      placement="bottom"
      arrow
      enter="transition duration-[1s] ease-out"
      enterFrom="scale-95 opacity-0"
      enterTo="scale-100 opacity-100"
      leave="transition duration-[0.5s] ease-in"
      leaveFrom="scale-100 opacity-100"
      leaveTo="scale-95 opacity-0"
      tailwindcssOriginClass
      composable
    >
      <Float.Reference>
        <div
          className="inline-block"
          onMouseEnter={() => setShow(true)}
          onMouseLeave={() => setShow(false)}
        >
          Hover me!
        </div>
      </Float.Reference>

      <Float.Content className="pointer-events-none">
        <div className="relative px-2 py-1 bg-gray-800 text-white rounded">
          <Float.Arrow className="absolute bg-gray-800 w-5 h-5 rotate-45" />
          <div className="relative">
            I am a tooltip!
          </div>
        </div>
      </Float.Content>
    </Float>
  )
}

If you have other questions, open a new issue and attach your sample code or minimally reproducible GitHub project. Online demo provided more <Flaot> examples.