Skip to content

Commit f6e63da

Browse files
Merge branch 'master' into feat/open-on-click
2 parents 2d921d7 + 06696b2 commit f6e63da

File tree

7 files changed

+156
-22
lines changed

7 files changed

+156
-22
lines changed

Diff for: docs/docs/examples/render.mdx

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
---
2+
sidebar_position: 1
3+
---
4+
5+
# Render
6+
7+
Using the ReactTooltip render prop to render dynamic content based on the active anchor element.
8+
9+
import { Tooltip } from 'react-tooltip'
10+
import 'react-tooltip/dist/react-tooltip.css'
11+
12+
export const TooltipAnchor = ({ children, id, ...rest }) => {
13+
return (
14+
<span
15+
id={id}
16+
style={{
17+
display: 'flex',
18+
justifyContent: 'center',
19+
margin: 'auto',
20+
alignItems: 'center',
21+
width: '60px',
22+
height: '60px',
23+
borderRadius: '60px',
24+
color: '#222',
25+
background: 'rgba(255, 255, 255, 1)',
26+
cursor: 'pointer',
27+
boxShadow: '3px 4px 3px rgba(0, 0, 0, 0.5)',
28+
border: '1px solid #333',
29+
}}
30+
{...rest}
31+
>
32+
{children}
33+
</span>
34+
)
35+
}
36+
37+
### Basic usage
38+
39+
The `render` prop can be used to render the tooltip content dynamically based on the currently active anchor element.
40+
The function signature is as follows:
41+
42+
```ts
43+
(render: { content: string | null; activeAnchor: HTMLElement | null }) => ChildrenType
44+
```
45+
46+
- `content` is available for quick access to the `data-tooltip-content` attribute on the anchor element
47+
- `activeAnchor` is a ref to the anchor element currently active (or `null` if no element is active)
48+
- `ChildrenType` is essentially the same as `React.ReactNode`
49+
50+
```jsx
51+
import { Tooltip } from 'react-tooltip';
52+
import 'react-tooltip/dist/react-tooltip.css';
53+
54+
<a
55+
data-tooltip-id="my-tooltip"
56+
data-tooltip-content="1"
57+
data-some-relevant-attr="wow"
58+
>
59+
◕‿‿◕
60+
</a>
61+
<a
62+
data-tooltip-id="my-tooltip"
63+
data-tooltip-content="2"
64+
data-some-relevant-attr="so relevant"
65+
>
66+
◕‿‿◕
67+
</a>
68+
<a
69+
data-tooltip-id="my-tooltip"
70+
data-tooltip-content="3"
71+
data-some-relevant-attr="much important"
72+
>
73+
◕‿‿◕
74+
</a>
75+
<Tooltip
76+
id="my-tooltip"
77+
render={({ content, activeAnchor }) => (
78+
<span>
79+
The element #{content} is currently active.
80+
<br/>
81+
Relevant attribute: {activeAnchor?.getAttribute('data-some-relevant-attr') || 'not set'}
82+
</span>
83+
)}
84+
/>
85+
```
86+
87+
<div style={{ display: 'flex', gap: '5px', width: 'fit-content', margin: 'auto' }}>
88+
<TooltipAnchor
89+
data-tooltip-id="my-tooltip"
90+
data-tooltip-content="1"
91+
data-some-relevant-attr="wow"
92+
>
93+
◕‿‿◕
94+
</TooltipAnchor>
95+
<TooltipAnchor
96+
data-tooltip-id="my-tooltip"
97+
data-tooltip-content="2"
98+
data-some-relevant-attr="so relevant"
99+
>
100+
◕‿‿◕
101+
</TooltipAnchor>
102+
<TooltipAnchor
103+
data-tooltip-id="my-tooltip"
104+
data-tooltip-content="3"
105+
data-some-relevant-attr="much important"
106+
>
107+
◕‿‿◕
108+
</TooltipAnchor>
109+
<Tooltip
110+
id="my-tooltip"
111+
render={({ content, activeAnchor }) => (
112+
<span>
113+
The element #{content} is currently active.
114+
<br/>
115+
Relevant attribute:{' '}
116+
{
117+
activeAnchor?.getAttribute('data-some-relevant-attr') || 'not set'
118+
}
119+
</span>
120+
)}
121+
/>
122+
</div>

Diff for: docs/docs/options.mdx

+6-5
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,15 @@ import 'react-tooltip/dist/react-tooltip.css'
100100
| `className` | `string` | no | | | Class name to customize tooltip element |
101101
| `classNameArrow` | `string` | no | | | Class name to customize tooltip arrow element |
102102
| `content` | `string` | no | | | Content to de displayed in tooltip (`html` prop is priorized over `content`) |
103-
| `html` | `string` | no | | | HTML content to de displayed in tooltip |
103+
| ~~`html`~~ | ~~`string`~~ | ~~no~~ | | | ~~HTML content to de displayed in tooltip~~ <br/>**DEPRECATED**<br/>Use `children` or `render` instead |
104+
| `render` | `function` | no | | | A function which receives a ref to the currently active anchor element and returns the content for the tooltip. Check the [examples](./examples/render.mdx) |
104105
| `place` | `string` | no | `top` | `top` `right` `bottom` `left` | Position relative to the anchor element where the tooltip will be rendered (if possible) |
105106
| `offset` | `number` | no | `10` | any `number` | Space between the tooltip element and anchor element (arrow not included in calculation) |
106107
| `id` | `string` | no | | any `string` | The tooltip id. Must be set when using `data-tooltip-id` on the anchor element |
107-
| ~~`anchorId`~~ | ~~`string`~~ | ~~no~~ | | ~~any `string`~~ | ~~The id for the anchor element for the tooltip~~ <br/>**DEPRECATED**<br/>Use `data-tooltip-id` or `anchorSelect` instead |
108-
| `anchorSelect` | CSS selector | no | | any valid CSS selector | The selector for the anchor elements. Check [the examples](./examples/anchor-select.mdx) for more details |
109-
| `variant` | `string` | no | `dark` | `dark` `light` `success` `warning` `error` `info` | Change the tooltip style with default presets |
110-
| `wrapper` | HTML tag | no | `div` | `div` `span` `p` ... | Element wrapper for the tooltip container, can be `div`, `span`, `p` or any valid HTML tag |
108+
| ~~`anchorId`~~ | ~~`string`~~ | ~~no~~ | | ~~any `string`~~ | ~~The id for the anchor element for the tooltip~~ <br/>**DEPRECATED**<br/>Use `data-tooltip-id` or `anchorSelect` instead |
109+
| `anchorSelect` | CSS selector | no | | any valid CSS selector | The selector for the anchor elements. Check [the examples](./examples/anchor-select.mdx) for more details |
110+
| `variant` | `string` | no | `dark` | `dark` `light` `success` `warning` `error` `info` | Change the tooltip style with default presets |
111+
| `wrapper` | HTML tag | no | `div` | `div` `span` `p` ... | Element wrapper for the tooltip container, can be `div`, `span`, `p` or any valid HTML tag |
111112
| `children` | React node | no | `undefined` | valid React children | The tooltip children have lower priority compared to the `content` prop and the `data-tooltip-content` attribute. Useful for setting default content |
112113
| ~~`events`~~ | ~~`string[]`~~ | ~~no~~ | ~~`hover`~~ | ~~`hover` `click`~~ | ~~Events to watch for when handling the tooltip state~~ <br/>**DEPRECATED**<br/>Use `openOnClick` tooltip prop instead |
113114
| `openOnClick` | `boolean` | no | `false` | `true` `false` | Controls whether the tooltip should open when clicking (`true`) or hovering (`false`) the anchor element |

Diff for: docs/docs/upgrade-guide/changelog-v4-v5.md

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ If you run into any problems with the tooltip not updating after changes are mad
4949
- [x] `setIsOpen` - `function` (to control tooltip state) - if not used, tooltip state will be handled internally
5050
- [x] `position` - `{ x: number; y: number }` - similar to V4's `overridePosition`
5151
- [x] `float` - `boolean` - used to achieve V4's `effect="float"`
52+
- [x] `render` - `function` - can be used to render dynamic content based on the active anchor element (check [the examples](../examples/render.mdx) for more details)
5253

5354
## `V4` props available in `V5`
5455

Diff for: src/components/Tooltip/Tooltip.tsx

+3-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { useEffect, useState, useRef } from 'react'
22
import classNames from 'classnames'
33
import debounce from 'utils/debounce'
4-
import { TooltipContent } from 'components/TooltipContent'
54
import { useTooltip } from 'components/TooltipProvider'
65
import useIsomorphicLayoutEffect from 'utils/use-isomorphic-layout-effect'
76
import { computeTooltipPosition } from '../../utils/compute-positions'
@@ -23,7 +22,6 @@ const Tooltip = ({
2322
positionStrategy = 'absolute',
2423
middlewares,
2524
wrapper: WrapperElement,
26-
children = null,
2725
delayShow = 0,
2826
delayHide = 0,
2927
float = false,
@@ -36,7 +34,6 @@ const Tooltip = ({
3634
afterHide,
3735
// props handled by controller
3836
content,
39-
html,
4037
isOpen,
4138
setIsOpen,
4239
activeAnchor,
@@ -471,7 +468,7 @@ const Tooltip = ({
471468
}
472469
setActualPlacement(computedStylesData.place as PlacesType)
473470
})
474-
}, [show, activeAnchor, content, html, place, offset, positionStrategy, position])
471+
}, [show, activeAnchor, content, place, offset, positionStrategy, position])
475472

476473
useEffect(() => {
477474
const anchorById = document.querySelector<HTMLElement>(`[id='${anchorId}']`)
@@ -514,8 +511,7 @@ const Tooltip = ({
514511
}
515512
}, [id, anchorSelect])
516513

517-
const hasContentOrChildren = Boolean(html || content || children)
518-
const canShow = hasContentOrChildren && show && Object.keys(inlineStyles).length > 0
514+
const canShow = content && show && Object.keys(inlineStyles).length > 0
519515

520516
return rendered ? (
521517
<WrapperElement
@@ -536,11 +532,7 @@ const Tooltip = ({
536532
style={{ ...externalStyles, ...inlineStyles }}
537533
ref={tooltipRef}
538534
>
539-
{/**
540-
* content priority: html > content > children
541-
* children should be last so that it can be used as the "default" content
542-
*/}
543-
{(html && <TooltipContent content={html} />) || content || children}
535+
{content}
544536
<WrapperElement
545537
className={classNames('react-tooltip-arrow', styles['arrow'], classNameArrow, {
546538
/**

Diff for: src/components/Tooltip/TooltipTypes.d.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ export interface IPosition {
3939
export interface ITooltip {
4040
className?: string
4141
classNameArrow?: string
42-
content?: string
43-
html?: string
42+
content?: ChildrenType
4443
place?: PlacesType
4544
offset?: number
4645
id?: string
@@ -52,7 +51,6 @@ export interface ITooltip {
5251
anchorId?: string
5352
anchorSelect?: string
5453
wrapper: WrapperType
55-
children?: ChildrenType
5654
/**
5755
* @deprecated Use `openOnClick` instead.
5856
*/

Diff for: src/components/TooltipController/TooltipController.tsx

+19-3
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ import type {
88
WrapperType,
99
DataAttribute,
1010
ITooltip,
11+
ChildrenType,
1112
} from 'components/Tooltip/TooltipTypes'
1213
import { useTooltip } from 'components/TooltipProvider'
14+
import { TooltipContent } from 'components/TooltipContent'
1315
import type { ITooltipController } from './TooltipControllerTypes'
1416

1517
const TooltipController = ({
@@ -18,6 +20,7 @@ const TooltipController = ({
1820
anchorSelect,
1921
content,
2022
html,
23+
render,
2124
className,
2225
classNameArrow,
2326
variant = 'dark',
@@ -197,14 +200,27 @@ const TooltipController = ({
197200
}
198201
}, [anchorRefs, providerActiveAnchor, activeAnchor, anchorId, anchorSelect])
199202

203+
/**
204+
* content priority: children < renderContent or content < html
205+
* children should be lower priority so that it can be used as the "default" content
206+
*/
207+
let renderedContent: ChildrenType = children
208+
if (render) {
209+
renderedContent = render({ content: tooltipContent ?? null, activeAnchor })
210+
} else if (tooltipContent) {
211+
renderedContent = tooltipContent
212+
}
213+
if (tooltipHtml) {
214+
renderedContent = <TooltipContent content={tooltipHtml} />
215+
}
216+
200217
const props: ITooltip = {
201218
id,
202219
anchorId,
203220
anchorSelect,
204221
className,
205222
classNameArrow,
206-
content: tooltipContent,
207-
html: tooltipHtml,
223+
content: renderedContent,
208224
place: tooltipPlace,
209225
variant: tooltipVariant,
210226
offset: tooltipOffset,
@@ -229,7 +245,7 @@ const TooltipController = ({
229245
setActiveAnchor: (anchor: HTMLElement | null) => setActiveAnchor(anchor),
230246
}
231247

232-
return children ? <Tooltip {...props}>{children}</Tooltip> : <Tooltip {...props} />
248+
return <Tooltip {...props} />
233249
}
234250

235251
export default TooltipController

Diff for: src/components/TooltipController/TooltipControllerTypes.d.ts

+4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ export interface ITooltipController {
1515
className?: string
1616
classNameArrow?: string
1717
content?: string
18+
/**
19+
* @deprecated Use `children` or `render` instead
20+
*/
1821
html?: string
22+
render?: (render: { content: string | null; activeAnchor: HTMLElement | null }) => ChildrenType
1923
place?: PlacesType
2024
offset?: number
2125
id?: string

0 commit comments

Comments
 (0)