Skip to content

Commit 50a8fd4

Browse files
committed
fix(Popover): do not trigger toggle on popover click
Closes #594
1 parent 3e9bf9e commit 50a8fd4

2 files changed

Lines changed: 46 additions & 5 deletions

File tree

src/Popover.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class Popover extends React.Component {
5050
this.addTargetEvents = this.addTargetEvents.bind(this);
5151
this.handleDocumentClick = this.handleDocumentClick.bind(this);
5252
this.removeTargetEvents = this.removeTargetEvents.bind(this);
53+
this.getRef = this.getRef.bind(this);
5354
this.toggle = this.toggle.bind(this);
5455
this.show = this.show.bind(this);
5556
this.hide = this.hide.bind(this);
@@ -70,6 +71,10 @@ class Popover extends React.Component {
7071
this.removeTargetEvents();
7172
}
7273

74+
getRef(ref) {
75+
this._popover = ref;
76+
}
77+
7378
getDelay(key) {
7479
const { delay } = this.props;
7580
if (typeof delay === 'object') {
@@ -115,7 +120,7 @@ class Popover extends React.Component {
115120
}
116121

117122
handleDocumentClick(e) {
118-
if (e.target !== this._target && !this._target.contains(e.target)) {
123+
if (e.target !== this._target && !this._target.contains(e.target) && e.target !== this._popover && !(this._popover && this._popover.contains(e.target))) {
119124
if (this._hideTimeout) {
120125
this.clearHideTimeout();
121126
}
@@ -172,7 +177,7 @@ class Popover extends React.Component {
172177
placementPrefix={this.props.placementPrefix}
173178
container={this.props.container}
174179
>
175-
<div {...attributes} className={classes} />
180+
<div {...attributes} className={classes} ref={this.getRef} />
176181
</PopperContent>
177182
);
178183
}

src/__tests__/Popover.spec.js

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ describe('Popover', () => {
1616
container = document.createElement('div');
1717
element.innerHTML = '<p id="outerTarget">This is the popover <span id="innerTarget">target</span>.</p>';
1818
container.setAttribute('id', 'container');
19-
outerTarget = document.getElementById('outerTarget');
20-
innerTarget = document.getElementById('innerTarget');
2119
element.appendChild(container);
2220
document.body.appendChild(element);
21+
outerTarget = document.getElementById('outerTarget');
22+
innerTarget = document.getElementById('innerTarget');
2323
isOpen = false;
2424
toggle = () => { isOpen = !isOpen; };
2525
placement = 'top';
@@ -221,7 +221,7 @@ describe('Popover', () => {
221221
wrapper.detach();
222222
});
223223

224-
it('should NOT handle inner target clicks', () => {
224+
it('should NOT handle inner target clicks when isOpen is false (user is responsible)', () => {
225225
const wrapper = mount(
226226
<Popover target="innerTarget" isOpen={isOpen} toggle={toggle}>
227227
Popover Content
@@ -238,6 +238,42 @@ describe('Popover', () => {
238238
wrapper.detach();
239239
});
240240

241+
it('should NOT handle inner target clicks when isOpen is true (user is responsible)', () => {
242+
isOpen = true;
243+
const wrapper = mount(
244+
<Popover target="innerTarget" isOpen={isOpen} toggle={toggle}>
245+
Popover Content
246+
</Popover>,
247+
{ attachTo: container }
248+
);
249+
const instance = wrapper.instance();
250+
251+
expect(isOpen).toBe(true);
252+
instance.handleDocumentClick({ target: innerTarget });
253+
jest.runTimersToTime(0); // toggle is still async
254+
expect(isOpen).toBe(true);
255+
256+
wrapper.detach();
257+
});
258+
259+
it('should NOT handle popover target clicks', () => {
260+
isOpen = true;
261+
const wrapper = mount(
262+
<Popover target="innerTarget" isOpen={isOpen} toggle={toggle}>
263+
Popover Content
264+
</Popover>,
265+
{ attachTo: container }
266+
);
267+
const instance = wrapper.instance();
268+
269+
expect(isOpen).toBe(true);
270+
instance.handleDocumentClick({ target: instance._popover });
271+
jest.runTimersToTime(0); // toggle is still async
272+
expect(isOpen).toBe(true);
273+
274+
wrapper.detach();
275+
});
276+
241277
it('should not do anything when document click outside of target', () => {
242278
const wrapper = mount(
243279
<Popover target="innerTarget" isOpen={isOpen} toggle={toggle}>

0 commit comments

Comments
 (0)