fix: make sure that voiceover + safari modals are accessible
This commit is contained in:
parent
6d2e9975af
commit
382a9aab64
3 changed files with 41 additions and 3 deletions
5
.changeset/wise-mirrors-grab.md
Normal file
5
.changeset/wise-mirrors-grab.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@lion/ui': patch
|
||||
---
|
||||
|
||||
make sure that voiceover + safari modals are accessible
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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', () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue