feat(overlay): add hide on outside esc handler

This commit is contained in:
Marcos Gil 2020-02-05 16:30:27 +01:00 committed by Thomas Allmer
parent 13a43fa402
commit c0ed437e8f
4 changed files with 37 additions and 35 deletions

View file

@ -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;

View file

@ -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>');

View file

@ -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: {

View file

@ -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>