diff --git a/docs/_includes/tooltip-documentation.md b/docs/_includes/tooltip-documentation.md index 877fc86d7d..76fdf54af8 100644 --- a/docs/_includes/tooltip-documentation.md +++ b/docs/_includes/tooltip-documentation.md @@ -34,6 +34,7 @@ Create a new Tooltip.js instance | [options.template] | String | '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>' | Base HTML to used when creating the tooltip. The tooltip's `title` will be injected into the `.tooltip-inner` or `.tooltip__inner`. `.tooltip-arrow` or `.tooltip__arrow` will become the tooltip's arrow. The outermost wrapper element should have the `.tooltip` class. | | options.title | String \| HTMLElement \| TitleFunction | '' | Default title value if `title` attribute isn't present. | | [options.trigger] | String | 'hover focus' | How tooltip is triggered - click, hover, focus, manual. You may pass multiple triggers; separate them with a space. `manual` cannot be combined with any other trigger. | +| options.closeOnClickOutside | Boolean | false | Close a popper on click outside of the popper and reference element. This has effect only when options.trigger is 'click'. | | options.boundariesElement | String \| HTMLElement | | The element used as boundaries for the tooltip. For more information refer to Popper.js' [boundariesElement docs](https://popper.js.org/popper-documentation.html) | | options.offset | Number \| String | 0 | Offset of the tooltip relative to its reference. For more information refer to Popper.js' [offset docs](https://popper.js.org/popper-documentation.html) | | options.popperOptions | Object | {} | Popper options, will be passed directly to popper instance. For more information refer to Popper.js' [options docs](https://popper.js.org/popper-documentation.html) | diff --git a/packages/tooltip/src/index.js b/packages/tooltip/src/index.js index 5813a74ca0..6af168dfaf 100644 --- a/packages/tooltip/src/index.js +++ b/packages/tooltip/src/index.js @@ -41,6 +41,7 @@ export default class Tooltip { * @param {String} [options.trigger='hover focus'] * How tooltip is triggered - click, hover, focus, manual. * You may pass multiple triggers; separate them with a space. `manual` cannot be combined with any other trigger. + * @param {Boolean} options.closeOnClickOutside=false - Close a popper on click outside of the popper and reference element. This has effect only when options.trigger is 'click'. * @param {String|HTMLElement} options.boundariesElement * The element used as boundaries for the tooltip. For more information refer to Popper.js' * [boundariesElement docs](https://popper.js.org/popper-documentation.html) @@ -354,6 +355,19 @@ export default class Tooltip { }; this._events.push({ event, func }); reference.addEventListener(event, func); + if (event === 'click' && options.closeOnClickOutside) { + document.addEventListener('mousedown', e => { + if (!this._isOpening) { + return; + } + const popper = this.popperInstance.popper; + if (reference.contains(e.target) || + popper.contains(e.target)) { + return; + } + func(e); + }, true); + } }); } diff --git a/packages/tooltip/tests/functional/tooltip.js b/packages/tooltip/tests/functional/tooltip.js index b8eef0132b..f04b03ec1b 100644 --- a/packages/tooltip/tests/functional/tooltip.js +++ b/packages/tooltip/tests/functional/tooltip.js @@ -512,5 +512,18 @@ describe('[tooltip.js]', () => { expect(instance._popperOptions.modifiers.offset.offset).toBe(10); done(); }); + + it('should hide on click outside with `options.closeOnClickOutside`', done => { + instance = new Tooltip(reference, { + title: 'foobar', + trigger: 'click', + closeOnClickOutside: true, + }); + reference.dispatchEvent(new CustomEvent('click')); + then(() => expect(document.querySelector('.tooltip')).not.toBeNull()); + then(() => document.body.dispatchEvent(new CustomEvent('mousedown'))); + then(() => expect(document.querySelector('.tooltip').style.visibility).toBe('hidden')); + then(done); + }); }); });