README.md
1# React Tooltip
2
3[![npm version](https://img.shields.io/npm/v/react-popper-tooltip.svg?style=flat-square)](https://www.npmjs.com/package/react-popper-tooltip)
4[![npm downloads](https://img.shields.io/npm/dm/react-popper-tooltip.svg?style=flat-square)](https://www.npmjs.com/package/react-popper-tooltip)
5[![codecov](https://codecov.io/gh/mohsinulhaq/react-popper-tooltip/branch/master/graph/badge.svg)](https://codecov.io/gh/mohsinulhaq/react-popper-tooltip)
6[![Dependency Status](https://img.shields.io/david/mohsinulhaq/react-popper-tooltip.svg?style=flat-square)](https://david-dm.org/mohsinulhaq/react-popper-tooltip)
7
8React tooltip component based on [react-popper](https://github.com/FezVrasta/react-popper), the React wrapper around [popper.js](https://popper.js.org/) library.
9
10## Homepage
11
12https://react-popper-tooltip.netlify.com
13
14## Example
15
16https://codesandbox.io/s/pykkz77z5j
17
18### Usage
19
20```bash
21npm install react-popper-tooltip
22```
23
24or
25
26```bash
27yarn add react-popper-tooltip
28```
29
30```jsx
31import React from 'react';
32import {render} from 'react-dom';
33import TooltipTrigger from 'react-popper-tooltip';
34
35const Tooltip = ({
36 arrowRef,
37 tooltipRef,
38 getArrowProps,
39 getTooltipProps,
40 placement
41}) => (
42 <div
43 {...getTooltipProps({
44 ref: tooltipRef,
45 className: 'tooltip-container'
46 /* your props here */
47 })}
48 >
49 <div
50 {...getArrowProps({
51 ref: arrowRef,
52 className: 'tooltip-arrow',
53 'data-placement': placement
54 /* your props here */
55 })}
56 />
57 Hello, World!
58 </div>
59);
60
61const Trigger = ({getTriggerProps, triggerRef}) => (
62 <span
63 {...getTriggerProps({
64 ref: triggerRef,
65 className: 'trigger'
66 /* your props here */
67 })}
68 >
69 Click Me!
70 </span>
71);
72
73render(
74 <TooltipTrigger placement="right" trigger="click" tooltip={Tooltip}>
75 {Trigger}
76 </TooltipTrigger>,
77 document.getElementById('root')
78);
79```
80
81`TooltipTrigger` is the only component exposed by the package. It's just a positioning engine. What to render is left completely to the user, which can be provided using render props. Your props should be passed through `getTriggerProps`, `getTooltipProps` and `getArrowProps`.
82
83Read more about [render prop](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce) pattern if you're not familiar with this approach.
84
85## Quick start
86
87If you would like our opinionated container and arrow styles for your tooltip for quick start, you may import `react-popper-tooltip/dist/styles.css`, and use the classes `tooltip-container` and `tooltip-arrow` as follows:
88
89### Tooltip.js
90
91```jsx
92import React from 'react';
93import TooltipTrigger from 'react-popper-tooltip';
94import 'react-popper-tooltip/dist/styles.css';
95
96const Tooltip = ({children, tooltip, hideArrow, ...props}) => (
97 <TooltipTrigger
98 {...props}
99 tooltip={({
100 arrowRef,
101 tooltipRef,
102 getArrowProps,
103 getTooltipProps,
104 placement
105 }) => (
106 <div
107 {...getTooltipProps({
108 ref: tooltipRef,
109 className: 'tooltip-container'
110 })}
111 >
112 {!hideArrow && (
113 <div
114 {...getArrowProps({
115 ref: arrowRef,
116 className: 'tooltip-arrow',
117 'data-placement': placement
118 })}
119 />
120 )}
121 {tooltip}
122 </div>
123 )}
124 >
125 {({getTriggerProps, triggerRef}) => (
126 <span
127 {...getTriggerProps({
128 ref: triggerRef,
129 className: 'trigger'
130 })}
131 >
132 {children}
133 </span>
134 )}
135 </TooltipTrigger>
136);
137
138export default Tooltip;
139```
140
141Then you can use it as shown in the example below.
142
143```jsx
144<Tooltip placement="top" trigger="click" tooltip="Hi there!">
145 Click me
146</Tooltip>
147```
148
149## Examples
150
151To fiddle with our example recipes, run:
152
153```bash
154> npm install
155> npm run docs
156```
157
158or
159
160```bash
161> yarn
162> yarn docs
163```
164
165and open up [localhost:3000](http://localhost:3000) in your browser.
166
167## Props
168
169### children
170
171> `function({})` | _required_
172
173This is called with an object. Read more about the properties of this object in
174the section "[Children and tooltip functions](#children-and-tooltip-functions)".
175
176### tooltip
177
178> `function({})` | _required_
179
180This is called with an object. Read more about the properties of this object in
181the section "[Children and tooltip functions](#children-and-tooltip-functions)".
182
183### defaultTooltipShown
184
185> `boolean` | defaults to `false`
186
187This is the initial visibility state of the tooltip.
188
189### onVisibilityChange
190
191> `function(tooltipShown: boolean)`
192
193Called with the tooltip state, when the visibility of the tooltip changes
194
195### tooltipShown
196
197> `boolean` | **control prop**
198
199Use this prop if you want to control the visibility state of the tooltip.
200
201`react-popper-tooltip` manages its own state internally. You can use this prop to pass the
202visibility state of the tooltip from the outside. You will be required to keep this state up to
203date (this is where `onVisibilityChange` becomes useful), but you can also control the state
204from anywhere, be that state from other components, `redux`, `react-router`, or anywhere else.
205
206### delayShow
207
208> `number` | defaults to `0`
209
210Delay in showing the tooltip (ms).
211
212### delayHide
213
214> `number` | defaults to `0`
215
216Delay in hiding the tooltip (ms).
217
218### placement
219
220> `string` | defaults to `right`
221
222The tooltip placement. Valid placements are:
223
224- `auto`
225- `top`
226- `right`
227- `bottom`
228- `left`
229
230Each placement can have a variation from this list:
231
232- `-start`
233- `-end`
234
235### trigger
236
237> `string` or `string[]` | defaults to `"hover"`
238
239The event(s) that trigger the tooltip. One of `click`, `right-click`, `hover`, `focus`, and `none`, or an array of them.
240
241### getTriggerRef
242
243> `function(HTMLElement) => void`
244
245Function that can be used to obtain a trigger element reference.
246
247### closeOnOutOfBoundaries
248
249> `boolean` | defaults to `true`
250
251Whether to close the tooltip when it's trigger is out of the boundary.
252
253### usePortal
254
255> `boolean` | defaults to `true`
256
257Whether to use `React.createPortal` for creating tooltip.
258
259### portalContainer
260
261> `HTMLElement` | defaults to `document.body`
262
263Element to be used as portal container
264
265### followCursor
266
267> `boolean` | defaults to `false`
268
269Whether to spawn the tooltip at the cursor position.
270
271Recommended usage with hover trigger and no arrow element
272
273### modifiers
274
275> `object`
276
277Modifiers passed directly to the underlying popper.js instance.
278For more information, refer to Popper.js’
279[modifier docs](https://popper.js.org/popper-documentation.html#modifiers)
280
281Default modifiers:
282
283```
284{
285 preventOverflow: {
286 boundariesElement: 'viewport'
287 }
288}
289```
290
291### mutationObserverOptions
292
293> `object`
294
295Options to `MutationObserver`, used internally for updating tooltip position based on trigger DOM changes.
296For more information, refer to [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) docs.
297
298Default options:
299
300```
301{
302 childList: true,
303 subtree: true
304}
305```
306
307## Children and tooltip functions
308
309This is where you render whatever you want. `react-popper-tooltip` uses two render props `children`
310and `tooltip`. `Children` prop is used to trigger the appearance of the tooltip and `tooltip`
311displays the tooltip itself.
312
313You use it like so:
314
315```jsx
316const tooltip = (
317 <TooltipTrigger tooltip={tooltip => <div>{/* more jsx here */}</div>}>
318 {trigger => <div>{/* more jsx here */}</div>}
319 </TooltipTrigger>
320);
321```
322
323### prop getters
324
325> See [the blog post about prop getters](https://blog.kentcdodds.com/how-to-give-rendering-control-to-users-with-prop-getters-549eaef76acf)
326
327These functions are used to apply props to the elements that you render.
328It's advisable to pass all your props to that function rather than applying them on the element
329yourself to avoid your props being overridden (or overriding the props returned). For example
330`<button {...getTriggerProps({onClick: event => console.log(event))}>Click me</button>`
331
332### children function
333
334| property | type | description |
335| --------------- | -------------- | --------------------------------------------------------------------- |
336| triggerRef | `function ref` | returns the react ref you should apply to the trigger element. |
337| getTriggerProps | `function({})` | returns the props you should apply to the trigger element you render. |
338
339### tooltip function
340
341| property | type | description |
342| --------------- | -------------- | --------------------------------------------------------------------- |
343| arrowRef | `function ref` | return the react ref you should apply to the tooltip arrow element. |
344| tooltipRef | `function ref` | return the react ref you should apply to the tooltip element. |
345| getArrowProps | `function({})` | return the props you should apply to the tooltip arrow element. |
346| getTooltipProps | `function({})` | returns the props you should apply to the tooltip element you render. |
347| placement | `string` | return the dynamic placement of the tooltip. |
348
349## Inspiration and Thanks!
350
351This library is based on [react-popper](https://github.com/FezVrasta/react-popper), the official
352react wrapper around [Popper.js](https://popper.js.org).
353
354Using of render props, prop getters and doc style of this library are heavily inspired by
355[downshift](https://github.com/paypal/downshift).
356