🚀 Socket Launch Week 🚀 Day 1: Introducing .NET Support in Socket.Learn More

headlessui-float-react

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

headlessui-float-react

Easy use Headless UI for React with Floating UI (Popper.js)

0.5.1
Version published
Weekly downloads
23
53.33%
Maintainers
1
Weekly downloads
 
Created

Headless UI Float React

Easy use Headless UI for React with Floating UI (New version Popper.js) to position floating elements.

NPM Version Software License NPM Downloads

English | 繁體中文

  • 💙 Easy use Headless UI & Tailwind CSS
  • 💬 Floating UI (New version Popper.js) position floating elements
  • 🔔 Auto-update floating elements
  • ♾️ Support Transition
  • 🚪 Support Portal
  • ➡️ Support Arrow

Live demo

Installation

This package is require React, React DOM and Headless UI React, you must be installed them first.

# npm
npm i headlessui-float-react
# yarn
yarn add headlessui-float-react

Usage

Start by finding a Headless UI component that needs to position the element, such as the <Menu> component for this example. Import <Float> component:

import { Float } from 'headlessui-float-react'

Then wrap <Float> around <Menu.Button> and <Menu.Items>:

<Menu>
+ <Float>
    <Menu.Button className="...">
      Options
    </Menu.Button>

    <Menu.Items className="...">
      ...
    </Menu.Items>
+ </Float>
</Menu>

Note that <Float> must contain 2 child elements, the first is the reference element, and the second is the floating element. It can be a Headless UI component or an HTML element.

Then remove the "absolute", "right-0" and other positioning class from <Menu.Items>, and add the placement="bottom-end" attribute:

<Menu>
  <Float placement="bottom-end">
    ...
  </Float>
</Menu>

Remove the "mt-2" class from <Menu.Items>, and add the offset={4} attribute:

<Menu>
  <Float placement="bottom-end" offset={4}>
    ...
  </Float>
</Menu>

Then <Menu> can automatically position the inner <Menu.Items>.

In addition to <Menu>, the same can be used on <Listbox>, <Popover> or <Combobox> components, and you can use <Float> on any element that requires floating positioning.

Show/Hide

If the floating element is Headless UI component, since the control of display is in the Headless UI component, it can be used directly.

However, if you want to manually control the display of the floating element, need to set show:

const [show, setShow] = useState(false)

<Float show={show}>

If the floating element uses an HTML element instead of the Headless UI component, need to set show.

Floating UI Options

placement

Floating positioning placement:

<Float placement="left-start">

All 12 placement in the Floating UI can be used:

  • top
  • top-start
  • top-end
  • right
  • right-start
  • right-end
  • bottom
  • bottom-start
  • bottom-end
  • left
  • left-start
  • left-end

strategy

The type of CSS position property, absolute or fixed:

<Float strategy="fixed">

offset

The offset (px) of the floating element from the reference element:

<Float offset={8}>

More options supported by offset, refer to Floating UI's offset documentation: https://floating-ui.com/docs/offset

shift

Move the reference elements back into the view:

<Float shift>

Set the offset (px) of the floating element from the view border:

<Float shift={8}>

More options supported by shift, refer to Floating UI's shift documentation: https://floating-ui.com/docs/shift

flip

Change to the opposite placement to keep it in view:

flip cannot be used with autoPlacement

<Float flip>

Sets the minimum padding (px) of the floating element from the view border when flip:

<Float flip={10}>

More options supported by flip, refer to Floating UI's flip documentation: https://floating-ui.com/docs/flip

autoPlacement

Floating elements choose the placement with more space left:

autoPlacement cannot be used with flip

<Float autoPlacement>

More options supported by autoPlacement, refer to Floating UI's autoPlacement documentation: https://floating-ui.com/docs/autoPlacement

autoUpdate

Automatically update floating elements when needed, the default value is true. Can be set to false to disable autoUpdate:

<Float autoUpdate={false}>

More options supported by autoUpdate, refer to Floating UI's autoUpdate documentation: https://floating-ui.com/docs/autoUpdate

middleware

If the above basic settings do not satisfy your needs, you can add the Floating UI middleware yourself:

import { offset } from '@floating-ui/react-dom'

const middleware = [
  offset({
    mainAxis: 10,
    crossAxis: 6,
  }),
]

<Float middleware={middleware}>

Or pass a function to get reference elements and floating elements in the parameters:

const middleware = ({ referenceEl, floatingEl }) => [
  ...
]

Transition

<Float> use the <Transition> component, just adds the classes of transition:

<Float
  enter="transition duration-200 ease-out"
  enterFrom="scale-95 opacity-0"
  enterTo="scale-100 opacity-100"
  leave="transition duration-150 ease-in"
  leaveFrom="scale-100 opacity-100"
  leaveTo="scale-95 opacity-0"
  tailwindcssOriginClass
>

When tailwindcssOriginClass is enabled, the corresponding Tailwind CSS origin class will be automatically added according to the placement (e.g. top corresponds to origin-bottom class, bottom-start corresponds to origin-top-left class).

If using the tailwindcssOriginClass, also need to add the origin class to the safelist:

tailwind.config.js

const { tailwindcssOriginSafelist } = require('headlessui-float-react')

module.exports = {
  safelist: [...tailwindcssOriginSafelist],
}

If need to override the origin class, can use originClass.

<Float originClass="origin-top-left">

Arrow

First import the <Float.Arrow> component, and put it inside the floating element, then add the class:

<Popover>
  <Float>
    ...
    <Popover.Panel>
      {/* 加入箭頭 */}
      <Float.Arrow className="absolute bg-white w-5 h-5 rotate-45 border border-gray-200" />
      <div>
        Popover & arrow, content...
      </div>
    </Popover.Panel>
  </Float>
</Popover>

Then add the arrow prop in <Float>, and add :offset="15" to keep the arrow away from the reference element:

<Float arrow offset={15}>

Full example of the arrow:

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

export default function ArrowExample() {
  return (
    <Popover>
      <Float
        placement="bottom-start"
        offset={15}
        arrow
      >
        <Popover.Button className="px-5 py-2 bg-rose-50 hover:bg-rose-100 text-rose-500 rounded">
          Button
        </Popover.Button>

        <Popover.Panel className="w-[240px] h-[70px] bg-white border border-gray-200 rounded-md shadow-lg focus:outline-none">
          <Float.Arrow className="absolute bg-white w-5 h-5 rotate-45 border border-gray-200" />
          <div className="relative h-full bg-white p-3 text-rose-500 rounded-md">
            Popover & arrow, content...
          </div>
        </Popover.Panel>
      </Float>
    </Popover>
  )
}

z-index

CSS z-index property for the floating element, the default value is 9999, and other numbers can be set:

<Float zIndex={100}>

Portal

Append the floating element to <body>:

<Float portal>

Or can select other elements that already exist:

<Float portal="#other-root-element">

Transform / Position Absolute (top / left)

The default is to use CSS transform to position floating elements. If this causes a conflict in transform properties, can set false to use top / left for positioning:

<Float transform={false}>

High-Order Component

The high-order component can be easily applied in projects after customizing the <Float> component:

HighOrderFloat.jsx

import { Float } from 'headlessui-float-react'

export default function HighOrderFloat(props) {
  return (
    <Float
      offset={8}
      flip
      shift={6}
      portal
      enter="transition duration-200 ease-out"
      enterFrom="scale-95 opacity-0"
      enterTo="scale-100 opacity-100"
      leave="transition duration-150 ease-in"
      leaveFrom="scale-100 opacity-100"
      leaveTo="scale-95 opacity-0"
      tailwindcssOriginClass
      {...props}
    >
      {props.children}
    </Float>
  )
}

Used in the same way as <Float>. It can also override the defined prop in high-order component:

<Menu>
  <HighOrderFloat placement="bottom-end" offset={12}>
    <Menu.Button>
      Options
    </Menu.Button>
    <Menu.Items>
      ...
    </Menu.Items>
  </HighOrderFloat>
</Menu>

If you using the TypeScript, can add FloatProps type to props:

HighOrderFloat.tsx

import { Float, FloatProps } from 'headlessui-float-react'

export default function HighOrderFloat(props: FloatProps) {
  // ...
}

Component API

Float

PropTypeDefaultDescription
asString | ComponentdivThe element or component the floating element should render as.
showBooleanControl the floating element is show or not.
placementPlacementbottom-startFloating placement.
strategyStrategyabsoluteCSS position property of the floating element.
offsetNumber | Object | FunctionThe offset (px) of the floating element from the reference element.
shiftBoolean | Number | ObjectfalseMove the reference elements back into the view.
flipBoolean | Number | ObjectfalseChange to the opposite placement to keep it in view.
arrowBoolean | NumberfalseEnable arrow positioning.
autoPlacementBoolean | ObjectfalseFloating elements choose the placement with more space left.
autoUpdateBoolean | ObjecttrueAutomatically update floating elements when needed.
zIndexNumber9999CSS z-index property for the floating element.
enterStringClasses to add to the transitioning element during the entire enter phase.
enterFromStringClasses to add to the transitioning element before the enter phase starts.
enterToStringClasses to add to the transitioning element immediately after the enter phase starts.
leaveStringClasses to add to the transitioning element during the entire leave phase.
leaveFromStringClasses to add to the transitioning element before the leave phase starts.
leaveToStringClasses to add to the transitioning element immediately after the leave phase starts.
originClassString | FunctionThe origin class of transform.
tailwindcssOriginClassBooleanfalseEnable automatically setting Tailwind CSS origin class.
portalBoolean | StringfalseRender floating element in the other exists element.
transformBooleantrueUse CSS transform to positioning floating element.
middlewareArray | () => []() => []Floating UI middleware
onShow() => voidTriggered when the floating element is show.
onHide() => voidTriggered when the floating element is hide.
onUpdate() => voidTriggered when the floating element position is update.

Float.Arrow

PropTypeDefaultDescription
asString | ComponentdivThe element or component the arrow should render as.
offsetNumber4Offset of the arrow to the outside of the floating element.
Render PropDescription
placementCurrent floating element placement.

Credits

License

Under the MIT LICENSE

FAQs

Package last updated on 29 Apr 2022

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts