fix: make sure that voiceover + safari modals are accessible

This commit is contained in:
Thijs Louisse 2024-11-20 14:02:56 +01:00 committed by Thijs Louisse
parent 6d2e9975af
commit 382a9aab64
3 changed files with 41 additions and 3 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/ui': patch
---
make sure that voiceover + safari modals are accessible

View file

@ -1121,6 +1121,15 @@ export class OverlayController extends EventTarget {
if (this.manager) {
this.manager.disableTrapsKeyboardFocusForAll();
}
const isContentShadowHost = Boolean(this.contentNode.shadowRoot);
if (isContentShadowHost) {
// eslint-disable-next-line no-console
console.warn(
'[overlays]: For best accessibility (compatibility with Safari + VoiceOver), provide a contentNode that is not a host for a shadow root',
);
}
this._containFocusHandler = containFocus(this.contentNode);
this.__hasActiveTrapsKeyboardFocus = true;
if (this.manager) {

View file

@ -603,8 +603,8 @@ describe('OverlayController', () => {
event.keyCode = keyCodes.tab;
window.dispatchEvent(event);
expect(elOutside).to.not.equal(document.activeElement);
expect(input1).to.equal(document.activeElement);
expect(isActiveElement(elOutside)).to.be.false;
expect(isActiveElement(input1)).to.be.true;
});
it('allows to move the focus outside of the overlay if trapsKeyboardFocus is disabled', async () => {
@ -625,7 +625,7 @@ describe('OverlayController', () => {
input.focus();
simulateTab();
expect(elOutside).to.equal(document.activeElement);
expect(isActiveElement(elOutside)).to.be.true;
});
it('keeps focus within overlay with multiple overlays with all traps on true', async () => {
@ -648,6 +648,30 @@ describe('OverlayController', () => {
expect(ctrl0.hasActiveTrapsKeyboardFocus).to.be.true;
expect(ctrl1.hasActiveTrapsKeyboardFocus).to.be.false;
});
it('warns when contentNode is a host for a shadowRoot', async () => {
const warnSpy = sinon.spy(console, 'warn');
const contentNode = /** @type {HTMLDivElement} */ (await fixture(html` <div></div> `));
contentNode.attachShadow({ mode: 'open' });
const shadowRootContentNode = /** @type {HTMLElement} */ (
await fixture(html` <div><input id="input1" /><input id="input2" /></div> `)
);
contentNode.shadowRoot?.appendChild(shadowRootContentNode);
const ctrl = new OverlayController({
...withGlobalTestConfig(),
trapsKeyboardFocus: true,
contentNode,
});
await ctrl.show();
// @ts-expect-error
expect(console.warn.args[0][0]).to.equal(
'[overlays]: For best accessibility (compatibility with Safari + VoiceOver), provide a contentNode that is not a host for a shadow root',
);
warnSpy.restore();
});
});
describe('hidesOnEsc', () => {