fix(tooltip): make tooltip hide with what triggered it
This commit is contained in:
parent
73e2305164
commit
48a41c97bf
2 changed files with 100 additions and 28 deletions
|
|
@ -2,6 +2,12 @@ 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"]');
|
||||
|
|
@ -17,20 +23,51 @@ export class LionTooltip extends LionPopup {
|
|||
invokerNode: this.invokerNode,
|
||||
}),
|
||||
);
|
||||
this._show = () => this._controller.show();
|
||||
this._hide = () => this._controller.hide();
|
||||
|
||||
this.addEventListener('mouseenter', this._show);
|
||||
this.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.removeEventListener('mouseenter', this._show);
|
||||
this.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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,59 @@ describe('lion-tooltip', () => {
|
|||
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`
|
||||
<lion-tooltip>
|
||||
<div slot="content">Hey there</div>
|
||||
<lion-button slot="invoker">Tooltip button</lion-button>
|
||||
</lion-tooltip>
|
||||
`);
|
||||
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`
|
||||
<lion-tooltip>
|
||||
<div slot="content">Hey there</div>
|
||||
<lion-button slot="invoker">Tooltip button</lion-button>
|
||||
</lion-tooltip>
|
||||
`);
|
||||
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`
|
||||
<lion-tooltip>
|
||||
<div slot="content">Hey there</div>
|
||||
<lion-button slot="invoker">Tooltip button</lion-button>
|
||||
</lion-tooltip>
|
||||
`);
|
||||
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('inline-block');
|
||||
});
|
||||
|
||||
it('should tooltip contains html when specified in tooltip content body', async () => {
|
||||
const el = await fixture(html`
|
||||
<lion-tooltip>
|
||||
|
|
@ -49,24 +102,6 @@ describe('lion-tooltip', () => {
|
|||
});
|
||||
|
||||
describe('Accessibility', () => {
|
||||
it('should visible on focusin and hide on focusout', async () => {
|
||||
const el = await fixture(html`
|
||||
<lion-tooltip>
|
||||
<div slot="content">Hey there</div>
|
||||
<lion-button slot="invoker">Tooltip button</lion-button>
|
||||
</lion-tooltip>
|
||||
`);
|
||||
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 have a tooltip role set on the tooltip', async () => {
|
||||
const el = await fixture(html`
|
||||
<lion-tooltip>
|
||||
|
|
|
|||
Loading…
Reference in a new issue