fix(tooltip): keeps tooltip closed when invoker is disabled

This commit is contained in:
qa46hx 2020-10-15 12:59:18 +02:00 committed by jorenbroekema
parent 2dc85b14d3
commit baeedeeea6
4 changed files with 74 additions and 8 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/tooltip': patch
---
Keep tooltip closed when invoker is disabled

View file

@ -47,18 +47,21 @@ const tooltipDemoStyles = css`
```js preview-story
export const main = () => html`
<style>${tooltipDemoStyles}</style>
<lion-tooltip>
<button slot="invoker" class="demo-tooltip-invoker">Hover me</button>
<div slot="content" class="demo-tooltip-content">This is a tooltip<div>
</lion-tooltip>
`;
<style>
${tooltipDemoStyles}
</style>
<lion-tooltip>
<button slot="invoker" class="demo-tooltip-invoker">Hover me</button>
<div slot="content" class="demo-tooltip-content">This is a tooltip</div>
</lion-tooltip>
`;
```
## Features
- Show content when hovering the invoker
- Show content when the invoker is focused
- Does not show content when invoker is disabled
- Uses Popper.js under the hood, to have the content pop up relative to the invoker
- Use `.config` to override the overlay configuration
- Config has `popperConfig` property that has a one to one relation with Popper.js configuration API.

View file

@ -66,6 +66,16 @@ export class LionTooltip extends ArrowMixin(OverlayMixin(LitElement)) {
});
}
_hasDisabledInvoker() {
if (this._overlayCtrl && this._overlayCtrl.invoker) {
return (
/** @type {HTMLElement & { disabled: boolean }} */ (this._overlayCtrl.invoker).disabled ||
this._overlayCtrl.invoker.getAttribute('aria-disabled') === 'true'
);
}
return false;
}
_setupOpenCloseListeners() {
super._setupOpenCloseListeners();
this.__resetActive = this.__resetActive.bind(this);
@ -98,7 +108,9 @@ export class LionTooltip extends ArrowMixin(OverlayMixin(LitElement)) {
_showMouse() {
if (!this._keyActive) {
this._mouseActive = true;
this.opened = true;
if (!this._hasDisabledInvoker()) {
this.opened = true;
}
}
}
@ -111,7 +123,9 @@ export class LionTooltip extends ArrowMixin(OverlayMixin(LitElement)) {
_showKey() {
if (!this._mouseActive) {
this._keyActive = true;
this.opened = true;
if (!this._hasDisabledInvoker()) {
this.opened = true;
}
}
}

View file

@ -102,6 +102,50 @@ describe('lion-tooltip', () => {
expect(el._overlayCtrl.isShown).to.equal(true);
});
it('stays hidden on disabled invoker', async () => {
const el = /** @type {LionTooltip} */ (await fixture(html`
<lion-tooltip>
<div slot="content">Hey there</div>
<button slot="invoker" disabled>Tooltip button</button>
</lion-tooltip>
`));
const invoker = /** @type {HTMLElement} */ (Array.from(el.children).find(
child => child.slot === 'invoker',
));
const eventMouseEnter = new Event('mouseenter');
el.dispatchEvent(eventMouseEnter);
await el.updateComplete;
// @ts-expect-error allow protected props in tests
expect(el._overlayCtrl.isShown).to.equal(false);
const eventFocusIn = new Event('focusin');
invoker.dispatchEvent(eventFocusIn);
await el.updateComplete;
// @ts-expect-error allow protected props in tests
expect(el._overlayCtrl.isShown).to.equal(false);
});
it('stays hidden on aria-disabled invoker', async () => {
const el = /** @type {LionTooltip} */ (await fixture(html`
<lion-tooltip>
<div slot="content">Hey there</div>
<button slot="invoker" aria-disabled="true">Tooltip button</button>
</lion-tooltip>
`));
const invoker = /** @type {HTMLElement} */ (Array.from(el.children).find(
child => child.slot === 'invoker',
));
const eventMouseEnter = new Event('mouseenter');
el.dispatchEvent(eventMouseEnter);
await el.updateComplete;
// @ts-expect-error allow protected props in tests
expect(el._overlayCtrl.isShown).to.equal(false);
const eventFocusIn = new Event('focusin');
invoker.dispatchEvent(eventFocusIn);
await el.updateComplete;
// @ts-expect-error allow protected props in tests
expect(el._overlayCtrl.isShown).to.equal(false);
});
it('contains html when specified in tooltip content body', async () => {
const el = /** @type {LionTooltip} */ (await fixture(html`
<lion-tooltip>