diff --git a/packages/components/src/components/tooltip/tooltip--definition.hbs b/packages/components/src/components/tooltip/tooltip--definition.hbs
index ff04e9c04fc7..46c36966a894 100644
--- a/packages/components/src/components/tooltip/tooltip--definition.hbs
+++ b/packages/components/src/components/tooltip/tooltip--definition.hbs
@@ -10,7 +10,8 @@
class="{{@root.prefix}}--tooltip__trigger {{@root.prefix}}--tooltip--a11y {{@root.prefix}}--tooltip__trigger--definition {{@root.prefix}}--tooltip--bottom {{@root.prefix}}--tooltip--align-start">
Definition Tooltip (start aligned)
-
Brief description of the dotted, underlined word
+
Brief description of the dotted,
+ underlined word
above.
Brief description of the dotted, underlined word
+
Brief description of the dotted,
+ underlined word
above.
Brief description of the dotted, underlined word
+
Brief description of the dotted,
+ underlined word
above.
diff --git a/packages/components/src/components/tooltip/tooltip--simple.js b/packages/components/src/components/tooltip/tooltip--simple.js
index a834f9b0499c..175086520dd6 100644
--- a/packages/components/src/components/tooltip/tooltip--simple.js
+++ b/packages/components/src/components/tooltip/tooltip--simple.js
@@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
+import debounce from 'lodash.debounce';
import settings from '../../globals/js/settings';
import mixin from '../../globals/js/misc/mixin';
import createComponent from '../../globals/js/mixins/create-component';
@@ -32,16 +33,28 @@ export default class TooltipSimple extends mixin(
// ESC
if (event.which === 27) {
this.allowTooltipVisibility({ visible: false });
+ const tooltipTriggerButton = this.getTooltipTriggerButton();
+ if (tooltipTriggerButton) {
+ tooltipTriggerButton.classList.remove(
+ this.options.classTooltipVisible
+ );
+ }
}
})
);
this.manage(
- on(this.element, 'mouseenter', () =>
- this.allowTooltipVisibility({ visible: true })
- )
+ on(this.element, 'mouseenter', () => {
+ this.tooltipFadeOut.cancel();
+ this.allowTooltipVisibility({ visible: true });
+ const tooltipTriggerButton = this.getTooltipTriggerButton();
+ if (tooltipTriggerButton) {
+ tooltipTriggerButton.classList.add(this.options.classTooltipVisible);
+ }
+ })
);
+ this.manage(on(this.element, 'mouseleave', this.tooltipFadeOut));
this.manage(
- on(this.element, 'focus', event => {
+ on(this.element, 'focusin', event => {
if (eventMatches(event, this.options.selectorTriggerButton)) {
this.allowTooltipVisibility({ visible: true });
}
@@ -49,13 +62,21 @@ export default class TooltipSimple extends mixin(
);
}
- allowTooltipVisibility = ({ visible }) => {
- const tooltipTriggerButton = this.element.matches(
- this.options.selectorTriggerButton
- )
+ tooltipFadeOut = debounce(() => {
+ const tooltipTriggerButton = this.getTooltipTriggerButton();
+ if (tooltipTriggerButton) {
+ tooltipTriggerButton.classList.remove(this.options.classTooltipVisible);
+ }
+ }, 100);
+
+ getTooltipTriggerButton = () =>
+ this.element.matches(this.options.selectorTriggerButton)
? this.element
: this.element.querySelector(this.options.selectorTriggerButton);
+ allowTooltipVisibility = ({ visible }) => {
+ const tooltipTriggerButton = this.getTooltipTriggerButton();
+
if (!tooltipTriggerButton) {
return;
}
@@ -83,6 +104,7 @@ export default class TooltipSimple extends mixin(
selectorInit: '[data-tooltip-definition],[data-tooltip-icon]',
selectorTriggerButton: `.${prefix}--tooltip__trigger.${prefix}--tooltip--a11y`,
classTooltipHidden: `${prefix}--tooltip--hidden`,
+ classTooltipVisible: `${prefix}--tooltip--visible`,
};
}
diff --git a/packages/components/src/globals/scss/_tooltip.scss b/packages/components/src/globals/scss/_tooltip.scss
index 6b491aeeabe4..d8a04afbe04f 100644
--- a/packages/components/src/globals/scss/_tooltip.scss
+++ b/packages/components/src/globals/scss/_tooltip.scss
@@ -40,7 +40,6 @@
font-weight: 400;
text-align: left;
transform: translateX(-50%);
- pointer-events: none;
background-color: $inverse-02;
@include type-style('body-short-01');
@@ -97,7 +96,6 @@
display: flex;
align-items: center;
opacity: 0;
- pointer-events: none;
// IE media query
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
@@ -150,6 +148,7 @@
content: none;
}
+ &.#{$prefix}--tooltip--visible,
&:hover,
&:focus {
&::before,
diff --git a/packages/components/tests/spec/tooltip--simple_spec.js b/packages/components/tests/spec/tooltip--simple_spec.js
index 8f95871f9005..21698e188d31 100644
--- a/packages/components/tests/spec/tooltip--simple_spec.js
+++ b/packages/components/tests/spec/tooltip--simple_spec.js
@@ -1,3 +1,4 @@
+import Promise, { delay } from 'bluebird';
import Tooltip from '../../src/components/tooltip/tooltip--simple';
import TooltipDefinitionHTML from '../../html/tooltip/tooltip--definition.html';
import TooltipIconHTML from '../../html/tooltip/tooltip--icon.html';
@@ -88,6 +89,23 @@ describe('Test simple tooltip', function() {
expect(element.classList.contains('bx--tooltip--hidden')).toBe(false);
});
+ it('Should have visible class after mouseenter', function() {
+ element.dispatchEvent(new CustomEvent('mouseenter', { bubbles: true }));
+ expect(element.classList.contains('bx--tooltip--visible')).toBe(true);
+ });
+
+ it('Should not have visible class after mouseleave', async function() {
+ await new Promise(resolve => {
+ resolve(
+ element.dispatchEvent(
+ new CustomEvent('mouseleave', { bubbles: true })
+ )
+ );
+ });
+ await delay(100);
+ expect(element.classList.contains('bx--tooltip--visible')).toBe(false);
+ });
+
it('Should not have hidden class after focus', function() {
element.dispatchEvent(new CustomEvent('focus', { bubbles: true }));
expect(element.classList.contains('bx--tooltip--hidden')).toBe(false);
diff --git a/packages/react/src/components/TooltipDefinition/TooltipDefinition.js b/packages/react/src/components/TooltipDefinition/TooltipDefinition.js
index 000c1deeff4b..7d8655be810b 100644
--- a/packages/react/src/components/TooltipDefinition/TooltipDefinition.js
+++ b/packages/react/src/components/TooltipDefinition/TooltipDefinition.js
@@ -9,6 +9,7 @@ import cx from 'classnames';
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { settings } from 'carbon-components';
+import debounce from 'lodash.debounce';
import setupGetInstanceId from '../../tools/setupGetInstanceId';
import { composeEventHandlers } from '../../tools/events';
import { keys, matches } from '../../internal/keyboard';
@@ -24,10 +25,12 @@ const TooltipDefinition = ({
align,
onFocus,
onMouseEnter,
+ onMouseLeave,
tooltipText,
...rest
}) => {
const [allowTooltipVisibility, setAllowTooltipVisibility] = useState(true);
+ const [tooltipVisible, setTooltipVisible] = useState(false);
const tooltipId = id || `definition-tooltip-${getInstanceId()}`;
const tooltipClassName = cx(
`${prefix}--tooltip--definition`,
@@ -43,10 +46,17 @@ const TooltipDefinition = ({
[`${prefix}--tooltip--${direction}`]: direction,
[`${prefix}--tooltip--align-${align}`]: align,
[`${prefix}--tooltip--hidden`]: !allowTooltipVisibility,
+ [`${prefix}--tooltip--visible`]: tooltipVisible,
}
);
+ const debounceTooltipVisible = debounce(() => setTooltipVisible(false), 100);
const handleFocus = () => setAllowTooltipVisibility(true);
- const handleMouseEnter = () => setAllowTooltipVisibility(true);
+ const handleMouseEnter = () => {
+ debounceTooltipVisible.cancel();
+ setAllowTooltipVisibility(true);
+ setTooltipVisible(true);
+ };
+ const handleMouseLeave = debounceTooltipVisible;
useEffect(() => {
const handleEscKeyDown = event => {
if (matches(event, [keys.Escape])) {
@@ -61,7 +71,8 @@ const TooltipDefinition = ({
+ onMouseEnter={composeEventHandlers([onMouseEnter, handleMouseEnter])}
+ onMouseLeave={composeEventHandlers([onMouseLeave, handleMouseLeave])}>