Skip to content

Commit f6dcc7c

Browse files
Add onVisibilityChange, update README
1 parent e9acd79 commit f6dcc7c

File tree

3 files changed

+48
-33
lines changed

3 files changed

+48
-33
lines changed

README.md

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,22 @@ the section "[Children and tooltip functions](#children-and-tooltip-functions)".
154154
155155
This is the initial visibility state of the tooltip.
156156

157+
### onVisibilityChange
158+
159+
> `function(tooltipShown: boolean)`
160+
161+
Called when the visibility of the tooltip changes. `tooltipShown` is a new state.
162+
157163
### tooltipShown
158164

159165
> `boolean` | **control prop**
160166
161167
Use this prop if you want to control the visibility state of the tooltip.
162168

163-
Package manages its own state internally. You can use this prop to pass the visibility state of the
164-
tooltip from the outside.
169+
`react-popper-tooltip` manages its own state internally. You can use this prop to pass the
170+
visibility state of the tooltip from the outside. You will be required to keep this state up to
171+
date (this is where `onVisibilityChange` becomes usefull), but you can also control the state
172+
from anywhere, be that state from other components, `redux`, `react-router`, or anywhere else.
165173

166174
### delayShow
167175

@@ -221,15 +229,6 @@ Modifiers, applied by default:
221229
}
222230
```
223231

224-
You also have the ability to attach ref to the `TooltipTrigger` component which exposes following
225-
methods for programmatic control of the tooltip:
226-
- `showTooltip` (show immediately)
227-
- `hideTooltip` (hide immediately)
228-
- `toggleTooltip` (toggle immediately)
229-
- `scheduleShow` (show respecting delayShow prop)
230-
- `scheduleHide` (hide respecting delayHide prop)
231-
- `scheduleToggle` (toggle respecting delayShow and delayHide props)
232-
233232
## Children and tooltip functions
234233

235234
This is where you render whatever you want. `react-popper-tooltip` uses two render props `children`

src/TooltipTrigger.js

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { createPortal } from 'react-dom';
66
import T from 'prop-types';
77
import { Manager, Reference, Popper } from 'react-popper';
88
import Tooltip from './Tooltip';
9-
import { callAll } from './utils';
9+
import { callAll, noop } from './utils';
1010

1111
const DEFAULT_MODIFIERS = {
1212
preventOverflow: {
@@ -35,6 +35,10 @@ export default class TooltipTrigger extends PureComponent {
3535
* use to create controlled tooltip
3636
*/
3737
tooltipShown: T.bool,
38+
/**
39+
* use to create controlled tooltip
40+
*/
41+
onVisibilityChange: T.func,
3842
/**
3943
* delay in showing the tooltip
4044
*/
@@ -77,11 +81,34 @@ export default class TooltipTrigger extends PureComponent {
7781
defaultTooltipShown: false,
7882
placement: 'right',
7983
trigger: 'hover',
80-
closeOnOutOfBoundaries: true
84+
closeOnOutOfBoundaries: true,
85+
onChange: noop
8186
};
8287

8388
state = {
84-
tooltipShown: this.props.defaultTooltipShown
89+
tooltipShown: this._isControlled()
90+
? undefined
91+
: this.props.defaultTooltipShown || false
92+
};
93+
94+
_isControlled() {
95+
return this.props.tooltipShown !== undefined;
96+
}
97+
98+
_getState() {
99+
return this._isControlled()
100+
? this.props.tooltipShown
101+
: this.state.tooltipShown;
102+
}
103+
104+
_setTooltipState = state => {
105+
const cb = () => this.props.onVisibilityChange(state);
106+
107+
if (this._isControlled()) {
108+
cb();
109+
} else {
110+
this.setState({ tooltipShown: state }, cb);
111+
}
85112
};
86113

87114
_clearScheduled = () => {
@@ -91,37 +118,24 @@ export default class TooltipTrigger extends PureComponent {
91118

92119
_showTooltip = (delay = this.props.delayShow) => {
93120
this._clearScheduled();
94-
95-
this._showTimeout = setTimeout(
96-
() => this.setState({ tooltipShown: true }),
97-
delay
98-
);
121+
this._showTimeout = setTimeout(() => this._setTooltipState(true), delay);
99122
};
100123

101124
_hideTooltip = (delay = this.props.delayHide) => {
102125
this._clearScheduled();
103-
104-
this._hideTimeout = setTimeout(
105-
() => this.setState({ tooltipShown: false }),
106-
delay
107-
);
126+
this._hideTimeout = setTimeout(() => this._setTooltipState(false), delay);
108127
};
109128

110129
_toggleTooltip = delay => {
111-
const action = this.state.tooltipShown ? '_hideTooltip' : '_showTooltip';
130+
const action = this._getState() ? '_hideTooltip' : '_showTooltip';
112131
this[action](delay);
113132
};
114133

115134
_contextMenuToggle = event => {
116135
event.preventDefault();
117-
this.scheduleToggle();
136+
this._toggleTooltip();
118137
};
119138

120-
static getDerivedStateFromProps(props) {
121-
const { tooltipShown } = props;
122-
return tooltipShown != null ? { tooltipShown } : null;
123-
}
124-
125139
componentWillUnmount() {
126140
this._clearScheduled();
127141
}
@@ -143,7 +157,7 @@ export default class TooltipTrigger extends PureComponent {
143157
props.onMouseEnter
144158
),
145159
onMouseLeave: callAll(
146-
isHoverTriggered && this._hideTooltip(),
160+
isHoverTriggered && this._hideTooltip,
147161
props.onMouseLeave
148162
)
149163
};
@@ -166,7 +180,7 @@ export default class TooltipTrigger extends PureComponent {
166180
children({ getTriggerProps: this.getTriggerProps, triggerRef: ref })
167181
}
168182
</Reference>
169-
{this.state.tooltipShown &&
183+
{this._getState() &&
170184
createPortal(
171185
<Popper
172186
placement={placement}

src/utils.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
export const callAll = (...fns) => (...args) =>
22
fns.forEach(fn => fn && fn(...args));
3+
4+
export const noop = () => {};

0 commit comments

Comments
 (0)