UNPKG

9.95 kBMarkdownView Raw
1## React Popper
2
3[![Build Status](https://travis-ci.org/FezVrasta/react-popper.svg?branch=master)](https://travis-ci.org/FezVrasta/react-popper)
4[![npm version](https://img.shields.io/npm/v/react-popper.svg)](https://www.npmjs.com/package/react-popper)
5[![npm downloads](https://img.shields.io/npm/dm/react-popper.svg)](https://www.npmjs.com/package/react-popper)
6[![Dependency Status](https://david-dm.org/souporserious/react-popper.svg)](https://david-dm.org/souporserious/react-popper)
7[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
8[![Get support or discuss](https://img.shields.io/badge/chat-on_spectrum-6833F9.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyBpZD0iTGl2ZWxsb18xIiBkYXRhLW5hbWU9IkxpdmVsbG8gMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMTAgOCI%2BPGRlZnM%2BPHN0eWxlPi5jbHMtMXtmaWxsOiNmZmY7fTwvc3R5bGU%2BPC9kZWZzPjx0aXRsZT5zcGVjdHJ1bTwvdGl0bGU%2BPHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNSwwQy40MiwwLDAsLjYzLDAsMy4zNGMwLDEuODQuMTksMi43MiwxLjc0LDMuMWgwVjcuNThhLjQ0LjQ0LDAsMCwwLC42OC4zNUw0LjM1LDYuNjlINWM0LjU4LDAsNS0uNjMsNS0zLjM1UzkuNTgsMCw1LDBaTTIuODMsNC4xOGEuNjMuNjMsMCwxLDEsLjY1LS42M0EuNjQuNjQsMCwwLDEsMi44Myw0LjE4Wk01LDQuMThhLjYzLjYzLDAsMSwxLC42NS0uNjNBLjY0LjY0LDAsMCwxLDUsNC4xOFptMi4xNywwYS42My42MywwLDEsMSwuNjUtLjYzQS42NC42NCwwLDAsMSw3LjE3LDQuMThaIi8%2BPC9zdmc%2B)](https://spectrum.chat/popper-js/react-popper)
9
10React wrapper around [Popper.js](https://popper.js.org).
11
12## Install
13
14Via package managers:
15
16```bash
17npm install react-popper@next --save
18# or
19yarn add react-popper@next
20```
21
22Via `script` tag (UMD library exposed as `ReactPopper`):
23
24```html
25<script src="https://unpkg.com/react-popper/dist/index.umd.js"></script>
26```
27
28## Usage
29
30> Using `react-popper@0.x`? You can find its documentation [clicking here](https://github.com/souporserious/react-popper/tree/v0.x)
31
32Example:
33
34```jsx
35import { Manager, Reference, Popper } from 'react-popper';
36
37const Example = () => (
38 <Manager>
39 <Reference>
40 {({ ref }) => (
41 <button type="button" ref={ref}>
42 Reference element
43 </button>
44 )}
45 </Reference>
46 <Popper placement="right">
47 {({ ref, style, placement, arrowProps }) => (
48 <div ref={ref} style={style} data-placement={placement}>
49 Popper element
50 <div ref={arrowProps.ref} style={arrowProps.style} />
51 </div>
52 )}
53 </Popper>
54 </Manager>
55);
56```
57
58`react-popper` makes use of a React pattern called **"render prop"**, if you are not
59familiar with it, please read more [on the official React documentation](https://reactjs.org/docs/render-props.html).
60
61> Using React <=15 or Preact? The components created with them don't support to return
62[fragments](https://reactjs.org/docs/fragments.html), this means that you will need to
63wrap `<Reference />` and `<Popper />` into a single, common, `<div />` to make `react-popper` work.
64
65### API documentation
66
67The `Manager` component is a simple wrapper that needs to surround all the other `react-popper` components in order
68to make them communicate with each others.
69
70The `Popper` component accepts the properties `children`, `placement`, `modifiers`, `eventsEnabled` and `positionFixed`.
71
72```jsx
73<Popper
74 innerRef={(node) => this.popperNode = node}
75 placement="right"
76 modifiers={{ preventOverflow: { enabled: false } }}
77 eventsEnabled={true}
78 positionFixed={false}
79>
80 { props => [...] }
81</Popper>
82```
83
84##### `children`
85
86```js
87children: ({|
88 ref: (?HTMLElement) => void,
89 style: { [string]: string | number },
90 placement: ?Placement,
91 outOfBoundaries: ?boolean,
92 scheduleUpdate: () => void,
93 arrowProps: {
94 ref: (?HTMLElement) => void,
95 style: { [string]: string | number },
96 },
97|}) => Node
98```
99
100A function (render prop) that takes as argument an object containing the properties
101`ref`, `style`, `placement`, and`arrowProps`.
102
103The first 3 properties are the `ref` property that is going to be used to retrieve the [React refs](https://reactjs.org/docs/refs-and-the-dom.html) of the **popper** element, the `style` property,
104which contains the CSS styles (React CSS properties) computed by Popper.js and needed to style
105the **popper** element so that it gets positioned in the desired way.
106These styles should be applied to your React component using the `style` prop or with any CSS-in-JS
107library of your choice.
108
109The `placement` property describes the placement of your popper after Popper.js has applied all the modifiers
110that may have flipped or altered the originally provided `placement` property. You can use this to alter the
111style of the popper and or of the arrow according to the definitive placement. For instance, you can use this
112property to orient the arrow to the right direction.
113
114`scheduleUpdate` is a function you can call to schedule a Popper.js position update. It will directly call the [Popper#scheduleUpdate](https://popper.js.org/popper-documentation.html#Popper.scheduleUpdate) method.
115
116The `arrowProps` argument is an object, containing a `style` and `ref` properties that are identical to the
117ones provided as first and second argument of `children`, but are relative to the **arrow** element rather than
118the popper. Use them to, accordingly, retrieve the ref of the **arrow** element and style it.
119
120##### `innerRef`
121```js
122innerRef?: (?HTMLElement) => void
123```
124
125Function that can be used to obtain popper reference
126
127##### `placement`
128
129```js
130placement?: PopperJS$Placement;
131```
132
133One of the accepted placement values listed in the [Popper.js documentation](https://popper.js.org/popper-documentation.html#Popper.placements).
134Your popper is going to be placed according to the value of this property.
135Defaults to `bottom`.
136
137```js
138outOfBoundaries: ?boolean;
139```
140
141A boolean that can be used to hide the popper element in case it's overflowing
142from its boundaries. [Read more](https://popper.js.org/popper-documentation.html#modifiers..hide).
143
144##### `eventsEnabled`
145
146```js
147eventsEnabled?: boolean;
148```
149
150Tells `react-popper` to enable or disable the [Popper.js event listeners](https://popper.js.org/popper-documentation.html#Popper.Defaults.eventsEnabled). `true` by default.
151
152##### `positionFixed`
153
154Set this property to `true` to tell Popper.js to use the `position: fixed` strategy
155to position the popper element. By default it's false, meaning that it will use the
156`position: absolute` strategy.
157
158##### `modifiers`
159
160```js
161modifiers?: PopperJS$Modifiers;
162```
163
164An object containing custom settings for the [Popper.js modifiers](https://popper.js.org/popper-documentation.html#modifiers).
165You can use this property to override their settings or to inject your custom ones.
166
167## Usage with `ReactDOM.createPortal`
168
169Popper.js is smart enough to work even if the **popper** and **reference** elements aren't
170in the same DOM context.
171This means that you can use [`ReactDOM.createPortal`](https://reactjs.org/docs/portals.html)
172(or any pre React 16 alternative) to move the popper component somewhere else in the DOM.
173
174This can be useful if you want to position a tooltip inside an `overflow: hidden` container
175that you want to make overflow. Please note that you can also try the `positionFixed` strategy
176to obtain a similar effect with less hassle.
177
178```jsx
179import { Manager, Reference, Popper } from 'react-popper';
180
181const Example = () => (
182 <Manager>
183 <Reference>
184 {({ ref }) => (
185 <button type="button" ref={ref}>
186 Reference
187 </button>
188 )}
189 </Reference>
190 {ReactDOM.createPortal(
191 <Popper>
192 {({ placement, ref, style }) => (
193 <div ref={ref} style={style} data-placement={placement}>
194 Popper
195 </div>
196 )}
197 </Popper>,
198 document.querySelector('#destination')
199 )}
200 </Manager>
201);
202```
203
204## Usage without a reference `HTMLElement`
205
206Whenever 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.
207
208The `referenceElement` property must be an object with an interface compatible with an `HTMLElement` as described in the [Popper.js referenceObject documentation](https://popper.js.org/popper-documentation.html#referenceObject), this implies that you may also provide a real HTMLElement if needed.
209
210If `referenceElement` is defined, it will take precedence over any `referenceProps.ref` provided refs.
211
212```jsx
213import { Popper } from 'react-popper';
214
215class VirtualReference {
216 getBoundingClientRect() {
217 return {
218 top: 10,
219 left: 10,
220 bottom: 20,
221 right: 100,
222 width: 90,
223 height: 10,
224 };
225 }
226
227 get clientWidth() {
228 return this.getBoundingClientRect().width;
229 }
230
231 get clientHeight() {
232 return this.getBoundingClientRect().height;
233 }
234}
235
236// This is going to create a virtual reference element
237// positioned 10px from top and left of the document
238// 90px wide and 10px high
239const virtualReferenceElement = new VirtualReference();
240
241// This popper will be positioned relatively to the
242// virtual reference element defined above
243const Example = () => (
244 <Popper referenceElement={virtualReferenceElement}>
245 {({ ref, style, placement, arrowProps }) => (
246 <div ref={ref} style={style} data-placement={placement}>
247 Popper element
248 <div ref={arrowProps.ref} style={arrowProps.style} />
249 </div>
250 )}
251 </Popper>
252);
253```
254
255## Flow and TypeScript types
256
257This library is built with Flow but it supports TypeScript as well.
258
259You can find the exported Flow types in `src/index.js`, and the
260TypeScript definitions in `typings/react-popper.d.ts`.
261
262## Running Locally
263
264#### clone repo
265
266`git clone git@github.com:FezVrasta/react-popper.git`
267
268#### move into folder
269
270`cd ~/react-popper`
271
272#### install dependencies
273
274`npm install` or `yarn`
275
276#### run dev mode
277
278`npm run demo:dev` or `yarn demo:dev`
279
280#### open your browser and visit:
281
282`http://localhost:1234/`