fix(overlays): only focus controlled elements after hide
This commit is contained in:
parent
d65ffd3c04
commit
f2d9b8e232
3 changed files with 34 additions and 6 deletions
5
.changeset/loud-rocks-teach.md
Normal file
5
.changeset/loud-rocks-teach.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@lion/overlays': patch
|
||||
---
|
||||
|
||||
only focus elements after hide when OverlayController has ownership
|
||||
|
|
@ -907,15 +907,19 @@ export class OverlayController extends EventTargetShim {
|
|||
|
||||
/** @protected */
|
||||
_restoreFocus() {
|
||||
const { activeElement } = /** @type {* & ShadowRoot} */ (this
|
||||
.__contentWrapperNode).getRootNode();
|
||||
// We only are allowed to move focus if we (still) 'own' it.
|
||||
// Otherwise we assume the 'outside world' has, purposefully, taken over
|
||||
if (
|
||||
activeElement &&
|
||||
/** @type {HTMLElement} */ (this.__contentWrapperNode).contains(activeElement)
|
||||
) {
|
||||
if (this.elementToFocusAfterHide) {
|
||||
this.elementToFocusAfterHide.focus();
|
||||
} else if (
|
||||
document.activeElement &&
|
||||
this.__contentWrapperNode?.contains(document.activeElement)
|
||||
) {
|
||||
/** @type {HTMLElement} */ (document.activeElement).blur();
|
||||
} else {
|
||||
activeElement.blur();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -741,6 +741,25 @@ describe('OverlayController', () => {
|
|||
expect(document.activeElement).to.equal(input);
|
||||
});
|
||||
|
||||
it(`only sets focus when outside world didn't take over already`, async () => {
|
||||
const input = /** @type {HTMLElement} */ (await fixture('<input />'));
|
||||
const outsideButton = /** @type {HTMLButtonElement} */ (await fixture('<button></button>'));
|
||||
const contentNode = /** @type {HTMLElement} */ (await fixture('<div>/div>'));
|
||||
const ctrl = new OverlayController({
|
||||
...withGlobalTestConfig(),
|
||||
elementToFocusAfterHide: input,
|
||||
contentNode,
|
||||
});
|
||||
|
||||
await ctrl.show();
|
||||
// an outside element has taken over focus
|
||||
outsideButton.focus();
|
||||
expect(document.activeElement).to.equal(outsideButton);
|
||||
|
||||
await ctrl.hide();
|
||||
expect(document.activeElement).to.equal(outsideButton);
|
||||
});
|
||||
|
||||
it('allows to set elementToFocusAfterHide on show', async () => {
|
||||
const input = /** @type {HTMLElement} */ (await fixture('<input />'));
|
||||
const contentNode = /** @type {HTMLElement} */ (await fixture(
|
||||
|
|
|
|||
Loading…
Reference in a new issue