Skip to content

Commit 471c4a3

Browse files
authored
Merge pull request #11 from mohsinulhaq/control-prop
Add onVisibilityChange, update README
2 parents dbfaeb4 + ed0258a commit 471c4a3

File tree

3 files changed

+44
-31
lines changed

3 files changed

+44
-31
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 useful), 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: 32 additions & 20 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+
* сalled when the visibility of the tooltip changes
40+
*/
41+
onVisibilityChange: T.func,
3842
/**
3943
* delay in showing the tooltip
4044
*/
@@ -77,11 +81,32 @@ export default class TooltipTrigger extends PureComponent {
7781
defaultTooltipShown: false,
7882
placement: 'right',
7983
trigger: 'hover',
80-
closeOnOutOfBoundaries: true
84+
closeOnOutOfBoundaries: true,
85+
onVisibilityChange: noop
8186
};
8287

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

87112
_clearScheduled = () => {
@@ -91,24 +116,16 @@ export default class TooltipTrigger extends PureComponent {
91116

92117
_showTooltip = (delay = this.props.delayShow) => {
93118
this._clearScheduled();
94-
95-
this._showTimeout = setTimeout(
96-
() => this.setState({ tooltipShown: true }),
97-
delay
98-
);
119+
this._showTimeout = setTimeout(() => this._setTooltipState(true), delay);
99120
};
100121

101122
_hideTooltip = (delay = this.props.delayHide) => {
102123
this._clearScheduled();
103-
104-
this._hideTimeout = setTimeout(
105-
() => this.setState({ tooltipShown: false }),
106-
delay
107-
);
124+
this._hideTimeout = setTimeout(() => this._setTooltipState(false), delay);
108125
};
109126

110127
_toggleTooltip = delay => {
111-
const action = this.state.tooltipShown ? '_hideTooltip' : '_showTooltip';
128+
const action = this._getState() ? '_hideTooltip' : '_showTooltip';
112129
this[action](delay);
113130
};
114131

@@ -117,11 +134,6 @@ export default class TooltipTrigger extends PureComponent {
117134
this._toggleTooltip();
118135
};
119136

120-
static getDerivedStateFromProps(props) {
121-
const { tooltipShown } = props;
122-
return tooltipShown != null ? { tooltipShown } : null;
123-
}
124-
125137
componentWillUnmount() {
126138
this._clearScheduled();
127139
}
@@ -166,7 +178,7 @@ export default class TooltipTrigger extends PureComponent {
166178
children({ getTriggerProps: this.getTriggerProps, triggerRef: ref })
167179
}
168180
</Reference>
169-
{this.state.tooltipShown &&
181+
{this._getState() &&
170182
createPortal(
171183
<Popper
172184
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)