Skip to content

React DOM Interactions

This package provides interaction primitives in the form of hooks and components that compose together to build higher-level floating UI components.

It works in tandem with the positioning engine to provide an accessible foundation for a <Tooltip />, <Popover />, <Select />, <Dropdown /> and other components.

Designed for all inputsSafe cursor polygon

It is a superset of the React DOM positioning engine package and is unrestricting, allowing you to incorporate custom logic easily.

View examples below.

Install

npm install @floating-ui/react-dom-interactions

Usage

The useFloating() hook exported from this package accepts an open boolean and onOpenChange as an option to change that value (plus all the positioning props as listed in the React DOM docs).

You use this boolean to conditionally render the floating element.

import {useState} from 'react';
import {useFloating} from '@floating-ui/react-dom-interactions';
 
function App() {
  const [open, setOpen] = useState(true);
  const {x, y, reference, floating, strategy} = useFloating({
    open,
    onOpenChange: setOpen,
  });
 
  return (
    <>
      <button ref={reference}>Button</button>
      {open && (
        <div
          ref={floating}
          style={{
            position: strategy,
            top: y ?? '',
            left: x ?? '',
          }}
        >
          Tooltip
        </div>
      )}
    </>
  );
}

Hooks

useInteractions() accepts an array of called hooks in the following predictable form:

import {
  useFloating,
  useInteractions,
  useHover,
  useFocus,
  useRole,
} from '@floating-ui/react-dom-interactions';
 
// ...
const {context} = useFloating();
const {getReferenceProps, getFloatingProps, getItemProps} =
  useInteractions([
    useHover(context, props),
    useFocus(context, props),
    useRole(context, props),
  ]);

Each hook accepts the context object which gets returned from useFloating() as its first argument. Props are passed as a second argument.

This API enables each of the hooks to be fully tree-shakeable. The navigation bar on the left explains them in detail.

Avoid importing all the hooks together like import * as Interactions from '@floating-ui/react-dom-interactions' as this will nullify the benefits of tree-shaking.

Prop getters

useInteractions() returns prop getters — functions you call to return props that spread on the elements:

<>
  <button {...getReferenceProps({ref: reference})}>
    My button
  </button>
  <div
    {...getFloatingProps({
      ref: floating,
      style: {
        position: strategy,
        left: x ?? '',
        top: y ?? '',
      },
    })}
  >
    My tooltip
  </div>
</>

This pattern enables you to pass event listener props through the prop getters, which performs merging of its own internal event listeners and your own without overriding them.

Item prop getter

When dealing with a list inside your floating element (useListNavigation()), pass these props to each item element:

<div
  {...getFloatingProps({
    ref: floating,
    style: {
      position: strategy,
      left: x ?? '',
      top: y ?? '',
    },
  })}
>
  <ul>
    {list.map((item) => (
      <li {...getItemProps({key: item})}>{item}</li>
    ))}
  </ul>
</div>

Without a list of items, this prop getter can be omitted (e.g. a regular tooltip or popover).

Examples

Here are a few example recipes for crafting common UI components (hosted on CodeSandbox).

Tooltip

Popover

Dialog

Context Menu

Select (Listbox)

The interaction hooks are low-level, so you probably won't be using them without wrapping them with your own component API for ergonomics.