Skip to content

Commit 545c19c

Browse files
authored
Merge pull request #502 from sonnenhaft/overridePosition-property
feat(overridePosition): Add "overridePosition" property to handle border cases and customize position
2 parents cfd5997 + 7df8454 commit 545c19c

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ className | data-class | String | | extra custom class, can use !importan
7373
getContent | null | Func or Array | (dataTip) => {}, [(dataTip) => {}, Interval] | Generate the tip content dynamically
7474
afterShow | null | Func | (evt) => {} | Function that will be called after tooltip show, with event that triggered show
7575
afterHide | null | Func | (evt) => {} | Function that will be called after tooltip hide, with event that triggered hide
76+
overridePosition | null | Func | ({left:number, top: number}, currentEvent, currentTarget, node, place, desiredPlace, effect, offset) => ({left: number, top: number}) | Function that will replace tooltip position with custom one
7677
disable | data-tip-disable | Bool | true, false | Disable the tooltip behaviour, default is false
7778
scrollHide | data-scroll-hide | Bool | true, false | Hide the tooltip when scrolling, default is true
7879
resizeHide | null | Bool | true, false | Hide the tooltip when resizing the window, default is true

example/src/index.js

+66
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,72 @@ class Test extends React.Component {
427427
</pre>
428428
</div>
429429

430+
<div className="section">
431+
<h4 className='title'>Override position</h4>
432+
<p className="sub-title">
433+
Try to resize/zoom in window - tooltip in this sample will try to
434+
magnet to window borders, top left border is priority here. Idea is following:
435+
sometimes you have custom border cases, like custom scrolls, small windows,
436+
iframes, react-tooltip itself can not cover everything, so up to you if you want to customize
437+
default behavior, or may be just limit it like in this example.
438+
</p>
439+
<div className="example-jsx">
440+
<div className="side" style={{display: 'flex', width: '100%'}}>
441+
<a data-tip data-for='overridePosition'>( •̀д•́) override</a>
442+
<ReactTooltip id='overridePosition' overridePosition={ ({ left, top },
443+
currentEvent, currentTarget, node) => {
444+
const d = document.documentElement;
445+
446+
left = Math.min(d.clientWidth - node.clientWidth, left);
447+
top = Math.min(d.clientHeight - node.clientHeight, top);
448+
449+
left = Math.max(0, left);
450+
top = Math.max(0, top);
451+
452+
return { top, left }
453+
} }>
454+
<div>header</div>
455+
<img src="http://lorempixel.com/100/1500" alt="lorem image 100x1500" />
456+
<div>footer</div>
457+
</ReactTooltip>
458+
<a data-tip data-for='noOverridePosition'>( •̀д•́) noOverride</a>
459+
<ReactTooltip id='noOverridePosition'>
460+
<div>header</div>
461+
<img src="http://lorempixel.com/100/1500" alt="lorem image 100x1500" />
462+
<div>footer</div>
463+
</ReactTooltip>
464+
</div>
465+
</div>
466+
<br />
467+
<pre className='example-pre'>
468+
<div>
469+
<p>{ `
470+
<a data-tip data-for='overridePosition'>( •̀д•́) override</a>
471+
<ReactTooltip id='overridePosition' overridePosition={ ({ left, top },
472+
currentEvent, currentTarget, node) => {
473+
const d = document.documentElement;
474+
475+
left = Math.min(d.clientWidth - node.clientWidth, left);
476+
top = Math.min(d.clientHeight - node.clientHeight, top);
477+
478+
left = Math.max(0, left);
479+
top = Math.max(0, top);
480+
481+
return { top, left }
482+
} }>
483+
<div>header</div>
484+
<img src="http://lorempixel.com/100/1500" alt="lorem image 100x1500" />
485+
<div>footer</div>
486+
</ReactTooltip>
487+
<a data-tip data-for='noOverridePosition'>( •̀д•́) noOverride</a>
488+
<ReactTooltip id='noOverridePosition'>
489+
<div>header</div>
490+
<img src="http://lorempixel.com/100/1500" alt="lorem image 100x1500" />
491+
<div>footer</div>
492+
</ReactTooltip>` }</p>
493+
</div>
494+
</pre>
495+
</div>
430496
</section>
431497
</div>
432498
)

src/index.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class ReactTooltip extends React.Component {
5353
getContent: PropTypes.any,
5454
afterShow: PropTypes.func,
5555
afterHide: PropTypes.func,
56+
overridePosition: PropTypes.func,
5657
disable: PropTypes.bool,
5758
scrollHide: PropTypes.bool,
5859
resizeHide: PropTypes.bool,
@@ -312,6 +313,10 @@ class ReactTooltip extends React.Component {
312313
let effect = switchToSolid && 'solid' || this.getEffect(e.currentTarget)
313314
let offset = e.currentTarget.getAttribute('data-offset') || this.props.offset || {}
314315
let result = getPosition(e, e.currentTarget, this.tooltipRef, desiredPlace, desiredPlace, effect, offset)
316+
if (result.position && this.props.overridePosition) {
317+
result.position = this.props.overridePosition(result.position, e.currentTarget, this.tooltipRef, desiredPlace, desiredPlace, effect, offset)
318+
}
319+
315320
let place = result.isNewState ? result.newState.place : desiredPlace
316321

317322
// To prevent previously created timers from triggering
@@ -483,7 +488,10 @@ class ReactTooltip extends React.Component {
483488
updatePosition () {
484489
const {currentEvent, currentTarget, place, desiredPlace, effect, offset} = this.state
485490
const node = this.tooltipRef
486-
const result = getPosition(currentEvent, currentTarget, node, place, desiredPlace, effect, offset)
491+
let result = getPosition(currentEvent, currentTarget, node, place, desiredPlace, effect, offset)
492+
if (result.position && this.props.overridePosition) {
493+
result.position = this.props.overridePosition(result.position, currentEvent, currentTarget, node, place, desiredPlace, effect, offset)
494+
}
487495

488496
if (result.isNewState) {
489497
// Switch to reverse placement

0 commit comments

Comments
 (0)