feat(overlay): add hide on outside esc handler
This commit is contained in:
parent
13a43fa402
commit
c0ed437e8f
4 changed files with 37 additions and 35 deletions
|
|
@ -32,6 +32,7 @@ export class OverlayController {
|
||||||
preventsScroll: false,
|
preventsScroll: false,
|
||||||
trapsKeyboardFocus: false,
|
trapsKeyboardFocus: false,
|
||||||
hidesOnEsc: false,
|
hidesOnEsc: false,
|
||||||
|
hidesOnOutsideEsc: false,
|
||||||
hidesOnOutsideClick: false,
|
hidesOnOutsideClick: false,
|
||||||
isTooltip: false,
|
isTooltip: false,
|
||||||
handlesUserInteraction: false,
|
handlesUserInteraction: false,
|
||||||
|
|
@ -376,6 +377,9 @@ export class OverlayController {
|
||||||
if (this.hidesOnEsc) {
|
if (this.hidesOnEsc) {
|
||||||
this._handleHidesOnEsc({ phase });
|
this._handleHidesOnEsc({ phase });
|
||||||
}
|
}
|
||||||
|
if (this.hidesOnOutsideEsc) {
|
||||||
|
this._handleHidesOnOutsideEsc({ phase });
|
||||||
|
}
|
||||||
if (this.hidesOnOutsideClick) {
|
if (this.hidesOnOutsideClick) {
|
||||||
this._handleHidesOnOutsideClick({ phase });
|
this._handleHidesOnOutsideClick({ phase });
|
||||||
}
|
}
|
||||||
|
|
@ -537,6 +541,15 @@ export class OverlayController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_handleHidesOnOutsideEsc({ phase }) {
|
||||||
|
if (phase === 'show') {
|
||||||
|
this.__escKeyHandler = ev => ev.key === 'Escape' && this.hide();
|
||||||
|
document.addEventListener('keyup', this.__escKeyHandler);
|
||||||
|
} else if (phase === 'hide') {
|
||||||
|
document.removeEventListener('keyup', this.__escKeyHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_handleInheritsReferenceWidth() {
|
_handleInheritsReferenceWidth() {
|
||||||
if (!this._referenceNode) {
|
if (!this._referenceNode) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -314,6 +314,29 @@ describe('OverlayController', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('hidesOnOutsideEsc', () => {
|
||||||
|
it('hides when [escape] is pressed on outside element', async () => {
|
||||||
|
const ctrl = new OverlayController({
|
||||||
|
...withGlobalTestConfig(),
|
||||||
|
hidesOnOutsideEsc: true,
|
||||||
|
});
|
||||||
|
await ctrl.show();
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keyup', { key: 'Escape' }));
|
||||||
|
await aTimeout();
|
||||||
|
expect(ctrl.isShown).to.be.false;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('stays shown when [escape] is pressed on inside element', async () => {
|
||||||
|
const ctrl = new OverlayController({
|
||||||
|
...withGlobalTestConfig(),
|
||||||
|
hidesOnOutsideEsc: true,
|
||||||
|
});
|
||||||
|
await ctrl.show();
|
||||||
|
ctrl.contentNode.dispatchEvent(new KeyboardEvent('keyup', { key: 'Escape' }));
|
||||||
|
expect(ctrl.isShown).to.be.true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('hidesOnOutsideClick', () => {
|
describe('hidesOnOutsideClick', () => {
|
||||||
it('hides on outside click', async () => {
|
it('hides on outside click', async () => {
|
||||||
const contentNode = await fixture('<div>Content</div>');
|
const contentNode = await fixture('<div>Content</div>');
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ export class LionTooltip extends OverlayMixin(LitElement) {
|
||||||
placementMode: 'local',
|
placementMode: 'local',
|
||||||
elementToFocusAfterHide: null,
|
elementToFocusAfterHide: null,
|
||||||
hidesOnEsc: true,
|
hidesOnEsc: true,
|
||||||
|
hidesOnOutsideEsc: true,
|
||||||
popperConfig: {
|
popperConfig: {
|
||||||
placement: 'top', // default
|
placement: 'top', // default
|
||||||
modifiers: {
|
modifiers: {
|
||||||
|
|
|
||||||
|
|
@ -85,41 +85,6 @@ describe('lion-tooltip', () => {
|
||||||
expect(el._overlayCtrl.isShown).to.equal(true);
|
expect(el._overlayCtrl.isShown).to.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show content on focusin and hide on Escape key press', async () => {
|
|
||||||
const el = await fixture(html`
|
|
||||||
<lion-tooltip>
|
|
||||||
<div slot="content">Hey there</div>
|
|
||||||
<button slot="invoker">Tooltip button</button>
|
|
||||||
</lion-tooltip>
|
|
||||||
`);
|
|
||||||
const invoker = Array.from(el.children).find(child => child.slot === 'invoker');
|
|
||||||
const eventFocusIn = new Event('focusin');
|
|
||||||
invoker.dispatchEvent(eventFocusIn);
|
|
||||||
await el.updateComplete;
|
|
||||||
expect(el._overlayCtrl.isShown).to.equal(true);
|
|
||||||
const eventEscapeKeypress = new KeyboardEvent('keyup', { key: 'Escape' });
|
|
||||||
invoker.dispatchEvent(eventEscapeKeypress);
|
|
||||||
await el.updateComplete;
|
|
||||||
expect(el._overlayCtrl.isShown).to.equal(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should show content on mouseenter and hide on Escape key press', async () => {
|
|
||||||
const el = await fixture(html`
|
|
||||||
<lion-tooltip>
|
|
||||||
<div slot="content">Hey there</div>
|
|
||||||
<button slot="invoker">Tooltip button</button>
|
|
||||||
</lion-tooltip>
|
|
||||||
`);
|
|
||||||
const eventMouseEnter = new Event('mouseenter');
|
|
||||||
el.dispatchEvent(eventMouseEnter);
|
|
||||||
await el.updateComplete;
|
|
||||||
expect(el._overlayCtrl.isShown).to.equal(true);
|
|
||||||
const eventEscapeKeypress = new KeyboardEvent('keyup', { key: 'Escape' });
|
|
||||||
document.dispatchEvent(eventEscapeKeypress);
|
|
||||||
await el.updateComplete;
|
|
||||||
expect(el._overlayCtrl.isShown).to.equal(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should tooltip contains html when specified in tooltip content body', async () => {
|
it('should tooltip contains html when specified in tooltip content body', async () => {
|
||||||
const el = await fixture(html`
|
const el = await fixture(html`
|
||||||
<lion-tooltip>
|
<lion-tooltip>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue