What is react-popper?
The react-popper package is a React wrapper around the Popper.js library, which is a positioning engine to ensure popovers, tooltips, and similar floating elements are positioned correctly relative to their reference elements, even in complex scenarios like inside scrolling containers or when the viewport size changes. It provides a set of React hooks and components to integrate Popper.js functionality in a React-friendly way.
What are react-popper's main functionalities?
Tooltip positioning
This code demonstrates how to use the `usePopper` hook to create a tooltip that is positioned relative to a button. The tooltip's position is automatically updated to ensure it remains correctly placed relative to the button, even if the layout changes.
{"import React from 'react';\nimport { usePopper } from 'react-popper';\n\nfunction Tooltip() {\n const [referenceElement, setReferenceElement] = useState(null);\n const [popperElement, setPopperElement] = useState(null);\n const { styles, attributes } = usePopper(referenceElement, popperElement);\n\n return (\n <>\n <button ref={setReferenceElement}>Hover over me</button>\n <div ref={setPopperElement} style={styles.popper} {...attributes.popper}>\n Tooltip content\n </div>\n </>\n );\n}"}
Dropdown menu
This example shows how to create a dropdown menu using `usePopper`. The dropdown's visibility is toggled by clicking a button, and its position is dynamically adjusted to stay aligned with the button.
{"import React, { useState } from 'react';\nimport { usePopper } from 'react-popper';\n\nfunction Dropdown() {\n const [referenceElement, setReferenceElement] = useState(null);\n const [popperElement, setPopperElement] = useState(null);\n const [visible, setVisible] = useState(false);\n const { styles, attributes } = usePopper(referenceElement, popperElement);\n\n return (\n <>\n <button ref={setReferenceElement} onClick={() => setVisible(!visible)}>Toggle Dropdown</button>\n {visible && (\n <div ref={setPopperElement} style={styles.popper} {...attributes.popper}>\n Dropdown content\n </div>\n )}\n </>\n );\n}"}
Other packages similar to react-popper
tippy.js
Tippy.js is a highly customizable tooltip and popover library that wraps around Popper.js, similar to react-popper but with a broader focus on tooltips and popovers. It offers a wide range of animations, themes, and interactive options out of the box, making it more feature-rich for specific tooltip and popover use cases compared to the more general positioning capabilities of react-popper.
floating-ui
Floating UI is the successor to Popper.js and offers direct React integration through its own React package. It provides low-level primitives for positioning floating elements, similar to react-popper, but with an updated API and additional features to handle more complex positioning scenarios. It's a more modern alternative with active development focusing on addressing limitations found in Popper.js.
React Popper
React wrapper around PopperJS.
Install
Via package managers:
npm install react-popper --save
yarn add react-popper
Via script
tag (UMD library exposed as ReactPopper
):
<script src="https://unpkg.com/react-popper/dist/react-popper.js"></script>
Usage
Example:
import Popper from 'react-popper';
const Example = () => (
<Popper placement="right">
{({ referenceProps, popperProps, arrowProps }) => (
<>
<button type="button" ref={referenceProps.getRef}>
Reference element
</button>
<div
ref={popperProps.getRef}
style={popperProps.style}
data-placement={popperProps.placement}
>
Popper element
<div ref={arrowProps.getRef} style={arrowProps.style} />
</div>
</>
)}
</Popper>
);
react-popper
makes use of a React pattern called "render prop", if you are not
familiar with it, please read more on the official React documentation.
API documentation
The Popper
component accepts the properties children
, placement
, modifiers
, and eventsEneabled
.
<Popper
placement="right"
modifiers={{ preventOverflow: { enabled: false } }}
eventsEnabled={true}
>
{ props => [...] }
</Popper>
children
children: ({|
referenceProps: {
getRef: (?HTMLElement) => void,
},
popperProps: {
getRef: (?HTMLElement) => void,
style: { [string]: string | number },
placement: ?Placement,
},
arrowProps: {
getRef: (?HTMLElement) => void,
style: { [string]: string | number },
placement: ?Placement,
},
|}) => Node
A function (render prop) that takes as argument an object containing the properties
referenceProps
, popperProps
, and arrowProps
.
These 3 properties are objects, each of them containing a getRef
property that is going to be used to retrieve the React refs of the 3 components needed by react-popper
: the reference, popper, and arrow.
popperProps
and arrowProps
, additionally, provide a style
property, which contains the CSS styles (React CSS properties) computed by Popper.js and needed to style the popper and arrow components so that they get positioned in the desired way. These styles should be applied to your React component usingthe style
prop or with any CSS-in-JS library of your choice.
They also provide a convenience property called placement
that is going to describe the placement of your popper after Popper.js has applied all the modifiers that may have flipped or altered the originally provided placement
property. You can use this to alter the style of the popper and or of the arrow according to the definitive placement. For instance, you can use this property to orient the arrow on the right direction.
placement
placement?: PopperJS$Placement;
One of the accepted placement values listed in the Popper.js documentation.
Your popper is going to be placed according to the value of this property.
Defaults to bottom
.
eventsEnabled
eventsEnabled?: boolean;
Tells react-popper
to enable or disable the Popper.js event listeners. true
by default.
modifiers
modifiers?: {
[string]: { order: number, enabled: boolean, fn: Object => Object },
};
An object containing custom settings for the Popper.js modifiers.
You can use this property to override their settings or to inject your custom ones.
Usage without a reference HTMLElement
Whenever you need to position a popper based on some arbitrary coordinates, you can provide Popper
with a referenceElement
property that is going to be used in place of the referenceProps.getRef
React ref.
The referenceElement
property must be an object with an interface compatible with an HTMLElement
as described in the Popper.js referenceObject documentation, this implies that you may also provide a real HTMLElement if needed.
If referenceElement
is defined, it will take precedence over any referenceProps.getRef
provied refs.
import Popper from 'react-popper';
class VirtualReference {
getBoundingClientRect() {
return {
top: 10,
left: 10,
bottom: 20,
right: 100,
width: 90,
height: 10,
};
}
get clientWidth() {
return this.getBoundingClientRect().width;
}
get clientHeight() {
return this.getBoundingClientRect().height;
}
}
const virtualReferenceElement = new VirtualReference();
const Example = () => (
<Popper referenceElement={virtualReferenceElement}>
{({ popperProps, arrowProps }) => (
<div
ref={popperProps.getRef}
style={popperProps.style}
data-placement={popperProps.placement}
>
Popper element
<div ref={arrowProps.getRef} style={arrowProps.style} />
</div>
)}
</Popper>
);
Running Locally
clone repo
git clone git@github.com:souporserious/react-popper.git
move into folder
cd ~/react-popper
install dependencies
npm install
or yarn
run dev mode
npm run dev
or yarn dev
open your browser and visit:
http://localhost:8080/