diff --git a/packages/popup/stories/index.stories.js b/packages/popup/stories/index.stories.js
index 6fa0bb8c6..c22745006 100644
--- a/packages/popup/stories/index.stories.js
+++ b/packages/popup/stories/index.stories.js
@@ -59,8 +59,8 @@ storiesOf('Local Overlay System|Popup', module)
-
Popup
+
`,
@@ -73,20 +73,20 @@ storiesOf('Local Overlay System|Popup', module)
-
Top
+
-
Right
+
-
Bottom
+
-
Left
+
`,
@@ -123,8 +123,8 @@ storiesOf('Local Overlay System|Popup', module)
},
})}"
>
-
${text('Invoker text', 'Click me!')}
+
`,
diff --git a/packages/tooltip/src/LionTooltip.js b/packages/tooltip/src/LionTooltip.js
index 87f5ab7ac..598efba08 100644
--- a/packages/tooltip/src/LionTooltip.js
+++ b/packages/tooltip/src/LionTooltip.js
@@ -2,10 +2,17 @@ import { LionPopup } from '@lion/popup';
import { overlays, LocalOverlayController } from '@lion/overlays';
export class LionTooltip extends LionPopup {
+ constructor() {
+ super();
+ this.mouseActive = false;
+ this.keyActive = false;
+ }
+
connectedCallback() {
super.connectedCallback();
this.contentNode = this.querySelector('[slot="content"]');
this.invokerNode = this.querySelector('[slot="invoker"]');
+ this.contentNode.setAttribute('role', 'tooltip');
this._controller = overlays.add(
new LocalOverlayController({
@@ -16,20 +23,51 @@ export class LionTooltip extends LionPopup {
invokerNode: this.invokerNode,
}),
);
- this._show = () => this._controller.show();
- this._hide = () => this._controller.hide();
- this.invokerNode.addEventListener('mouseenter', this._show);
- this.invokerNode.addEventListener('mouseleave', this._hide);
- this.invokerNode.addEventListener('focusin', this._show);
- this.invokerNode.addEventListener('focusout', this._hide);
+ this.__resetActive = () => {
+ this.mouseActive = false;
+ this.keyActive = false;
+ };
+
+ this.__showMouse = () => {
+ if (!this.keyActive) {
+ this.mouseActive = true;
+ this._controller.show();
+ }
+ };
+
+ this.__hideMouse = () => {
+ if (!this.keyActive) {
+ this._controller.hide();
+ }
+ };
+
+ this.__showKey = () => {
+ if (!this.mouseActive) {
+ this.keyActive = true;
+ this._controller.show();
+ }
+ };
+
+ this.__hideKey = () => {
+ if (!this.mouseActive) {
+ this._controller.hide();
+ }
+ };
+
+ this._controller.addEventListener('hide', this.__resetActive);
+ this.addEventListener('mouseenter', this.__showMouse);
+ this.addEventListener('mouseleave', this.__hideMouse);
+ this.invokerNode.addEventListener('focusin', this.__showKey);
+ this.invokerNode.addEventListener('focusout', this.__hideKey);
}
disconnectedCallback() {
super.disconnectedCallback();
- this.invokerNode.removeEventListener('mouseenter', this._show);
- this.invokerNode.removeEventListener('mouseleave', this._hide);
- this.invokerNode.removeEventListener('focusin', this._show);
- this.invokerNode.removeEventListener('focusout', this._hide);
+ this._controller.removeEventListener('hide', this.__resetActive);
+ this.removeEventListener('mouseenter', this.__showMouse);
+ this.removeEventListener('mouseleave', this._hideMouse);
+ this.invokerNode.removeEventListener('focusin', this._showKey);
+ this.invokerNode.removeEventListener('focusout', this._hideKey);
}
}
diff --git a/packages/tooltip/stories/index.stories.js b/packages/tooltip/stories/index.stories.js
index 0d7e4c1ac..9be5424ce 100644
--- a/packages/tooltip/stories/index.stories.js
+++ b/packages/tooltip/stories/index.stories.js
@@ -59,8 +59,8 @@ storiesOf('Local Overlay System|Tooltip', module)
- Hello there!
Tooltip
+ Hello there!
`,
@@ -73,20 +73,20 @@ storiesOf('Local Overlay System|Tooltip', module)
- Its top placement
Top
+ Its top placement
- Its right placement
Right
+ Its right placement
- Its bottom placement
Bottom
+ Its bottom placement
- Its left placement
Left
+ Its left placement
`,
@@ -123,8 +123,8 @@ storiesOf('Local Overlay System|Tooltip', module)
},
})}"
>
- ${text('Content text', 'Hello, World!')}
${text('Invoker text', 'Click me!')}
+ ${text('Content text', 'Hello, World!')}
`,
diff --git a/packages/tooltip/test/lion-tooltip.test.js b/packages/tooltip/test/lion-tooltip.test.js
index 14a4702bb..249f247ac 100644
--- a/packages/tooltip/test/lion-tooltip.test.js
+++ b/packages/tooltip/test/lion-tooltip.test.js
@@ -21,15 +21,67 @@ describe('lion-tooltip', () => {
Tooltip button
`);
- const invoker = el.querySelector('[slot="invoker"]');
const eventMouseEnter = new Event('mouseenter');
- invoker.dispatchEvent(eventMouseEnter);
+ el.dispatchEvent(eventMouseEnter);
+ await el.updateComplete;
+ expect(el.querySelector('[slot="content"]').style.display).to.be.equal('inline-block');
+ const eventMouseLeave = new Event('mouseleave');
+ el.dispatchEvent(eventMouseLeave);
+ await el.updateComplete;
+ expect(el.querySelector('[slot="content"]').style.display).to.be.equal('none');
+ });
+
+ it('should show content on mouseenter and remain shown on focusout', async () => {
+ const el = await fixture(html`
+
+ Hey there
+ Tooltip button
+
+ `);
+ const eventMouseEnter = new Event('mouseenter');
+ el.dispatchEvent(eventMouseEnter);
+ await el.updateComplete;
+ expect(el.querySelector('[slot="content"]').style.display).to.be.equal('inline-block');
+ const eventFocusOut = new Event('focusout');
+ el.dispatchEvent(eventFocusOut);
+ await el.updateComplete;
+ expect(el.querySelector('[slot="content"]').style.display).to.be.equal('inline-block');
+ });
+
+ it('should show content on focusin and hide on focusout', async () => {
+ const el = await fixture(html`
+
+ Hey there
+ Tooltip button
+
+ `);
+ const invoker = el.querySelector('[slot="invoker"]');
+ const eventFocusIn = new Event('focusin');
+ invoker.dispatchEvent(eventFocusIn);
+ await el.updateComplete;
+ expect(el.querySelector('[slot="content"]').style.display).to.be.equal('inline-block');
+ const eventFocusOut = new Event('focusout');
+ invoker.dispatchEvent(eventFocusOut);
+ await el.updateComplete;
+ expect(el.querySelector('[slot="content"]').style.display).to.be.equal('none');
+ });
+
+ it('should show content on focusin and remain shown on mouseleave', async () => {
+ const el = await fixture(html`
+
+ Hey there
+ Tooltip button
+
+ `);
+ const invoker = el.querySelector('[slot="invoker"]');
+ const eventFocusIn = new Event('focusin');
+ invoker.dispatchEvent(eventFocusIn);
await el.updateComplete;
expect(el.querySelector('[slot="content"]').style.display).to.be.equal('inline-block');
const eventMouseLeave = new Event('mouseleave');
invoker.dispatchEvent(eventMouseLeave);
await el.updateComplete;
- expect(el.querySelector('[slot="content"]').style.display).to.be.equal('none');
+ expect(el.querySelector('[slot="content"]').style.display).to.be.equal('inline-block');
});
it('should tooltip contains html when specified in tooltip content body', async () => {
@@ -50,22 +102,15 @@ describe('lion-tooltip', () => {
});
describe('Accessibility', () => {
- it('should visible on focusin and hide on focusout', async () => {
+ it('should have a tooltip role set on the tooltip', async () => {
const el = await fixture(html`
Hey there
Tooltip button
`);
- const invoker = el.querySelector('[slot="invoker"]');
- const eventFocusIn = new Event('focusin');
- invoker.dispatchEvent(eventFocusIn);
- await el.updateComplete;
- expect(el.querySelector('[slot="content"]').style.display).to.be.equal('inline-block');
- const eventFocusOut = new Event('focusout');
- invoker.dispatchEvent(eventFocusOut);
- await el.updateComplete;
- expect(el.querySelector('[slot="content"]').style.display).to.be.equal('none');
+ const invoker = el.querySelector('[slot="content"]');
+ expect(invoker.getAttribute('role')).to.be.equal('tooltip');
});
it('should have aria-controls attribute set to the invoker', async () => {