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
npm install react-popper --save
<script src="https://unpkg.com/react-popper/dist/react-popper.js"></script>
(UMD library exposed as `ReactPopper`)
Usage
import { Manager, Target, Popper, Arrow } from 'react-popper'
const PopperExample = () => (
<Manager>
<Target style={{ width: 120, height: 120, background: '#b4da55' }}>
Target Box
</Target>
<Popper placement="left" className="popper">
Left Content
<Arrow className="popper__arrow"/>
</Popper>
<Popper placement="right" className="popper">
Right Content
<Arrow className="popper__arrow"/>
</Popper>
</Manager>
)
Usage w/ child function
This is a useful way to interact with custom components. Just make sure you pass down the refs properly.
import { Manager, Target, Popper, Arrow } from 'react-popper'
const PopperExample = () => (
<Manager>
<Target>
{({ targetProps }) => (
<div {...targetProps}>
Target Box
</div>
)}
</Target>
<Popper placement="left">
{({ popperProps, restProps }) => (
<div
className="popper"
{...popperProps}
>
Popper Content
<Arrow>
{({ arrowProps, restProps }) => (
<span
className="popper__arrow"
{...arrowProps}
/>
)}
</Arrow>
</div>
)}
</Popper>
</Manager>
)
Shared Props
Target
, Popper
, and Arrow
all share the following props
component
: PropTypes.oneOfType([PropTypes.node, PropTypes.func])
A valid DOM tag or custom component to render. If using a custom component, an innerRef
prop will be passed down that must be attached to the child component ref.
innerRef
: PropTypes.func
Use this prop to access the internal ref. Does not apply to the Manager
component since we do not interact with its ref.
Manager
This is a special component that provides the Target
component to the Popper
component. Pass any props as you normally would here.
tag
: PropTypes.oneOfType([PropTypes.string, PropTypes.bool])
A valid DOM tag to render. Allows rendering just children by passing false
. Once React 16 is out, this prop will most likely go away since we will be able to return an array and all this currently does is subscribe Target
and Popper
.
Target
This is just a simple component that subscribes to PopperManager
, so Popper
can make use of it. Again, pass any props as you normally would here.
Each Target
must be wrapped in a Manager
, and each Manager
can wrap only one Target
.
children
: PropTypes.oneOfType([PropTypes.node, PropTypes.func])
A Target
's child may be one of the following:
-
a React element[s]
-
a function accepting the following object (all props must be passed down in order for the PopperJS to work properly)
{
targetProps: {
ref
},
restProps
}
Popper
Your popper that gets attached to the Target
component.
Each Popper
must be wrapped in a Manager
, and each Manager
can wrap multiple Popper
components.
placement
: PropTypes.oneOf(Popper.placements)
eventsEnabled
: PropTypes.bool
modifiers
: PropTypes.object
Passes respective options to a new Popper instance. As for onCreate
and onUpdate
, these callbacks were intentionally left out in favor of using the component lifecycle methods. If you have a good use case for these please feel free to file and issue and I will consider adding them in.
children
: PropTypes.oneOfType([PropTypes.node, PropTypes.func])
A Popper
's child may be one of the following:
-
a React element[s]
-
a function accepting the following object (all props must be passed down in order for the PopperJS to work properly)
{
popperProps: {
ref,
style,
['data-placement']
},
restProps
}
Arrow
Another component that subscribes to the Popper
component as an arrow modifier. Must be a child of Popper
.
children
: PropTypes.oneOfType([PropTypes.node, PropTypes.func])
An Arrow
's child may be one of the following:
-
a React element[s]
-
a function accepting the following object (all props must be passed down in order for the PopperJS to work properly)
{
arrowProps: {
ref,
style
},
restProps
}
Running Locally
clone repo
git clone git@github.com:souporserious/react-popper.git
move into folder
cd ~/react-popper
install dependencies
npm install
run dev mode
npm run dev
open your browser and visit: http://localhost:8080/