fix(@lion/ui): [select-rich] listbox element always focused in overlay
when the overlay is shown, the "autofocus" attribute is added to _listboxNode (_inputNode) to make sure that keyboard navigation continues to work when the element is inside a bottomsheet. When the overlay is closed the attribute is removed.
This commit is contained in:
parent
faae93376a
commit
84173cdba1
3 changed files with 44 additions and 0 deletions
5
.changeset/rich-apricots-argue.md
Normal file
5
.changeset/rich-apricots-argue.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@lion/ui': patch
|
||||
---
|
||||
|
||||
lion-select-rich: when the overlay is shown, the "autofocus" attribute is added to \_listboxNode (\_inputNode) to make sure that keyboard navigation continues to work when the element is inside a an element with `trapsKeyboardFocus:true`, like the bottomsheet created via `withBottomSheetConfig()`. When the overlay is closed the attribute is removed.
|
||||
|
|
@ -369,6 +369,11 @@ export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(L
|
|||
if (this.hasNoDefaultSelected) {
|
||||
this._noDefaultSelectedInheritsWidth();
|
||||
}
|
||||
|
||||
// When `trapsKeyboardFocus:true` is configured in our overlay, we need to make sure
|
||||
// that our element with [role=listbox] gets focus. The `containFocus` util will look
|
||||
// for an element with [autofocus] (otherwise it sets focus to `contentNode` (the 'root' of the overlay))
|
||||
this._listboxNode.setAttribute('autofocus', '');
|
||||
}
|
||||
|
||||
/** @private */
|
||||
|
|
@ -382,6 +387,7 @@ export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(L
|
|||
/** @private */
|
||||
__overlayOnHide() {
|
||||
this._invokerNode.focus();
|
||||
this._listboxNode.removeAttribute('autofocus');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -424,6 +424,39 @@ describe('lion-select-rich', () => {
|
|||
expect(el.singleOption).to.be.false;
|
||||
expect(_invokerNode.singleOption).to.be.false;
|
||||
});
|
||||
|
||||
it('adds/removes the autofocus attribute to/from _listboxNode', async () => {
|
||||
const el = await fixture(html` <lion-select-rich></lion-select-rich> `);
|
||||
const { _listboxNode } = getSelectRichMembers(el);
|
||||
|
||||
expect(_listboxNode.hasAttribute('autofocus')).to.be.false;
|
||||
|
||||
el.opened = true;
|
||||
await el.updateComplete;
|
||||
expect(_listboxNode.hasAttribute('autofocus')).to.be.true;
|
||||
|
||||
el.opened = false;
|
||||
await el.updateComplete;
|
||||
await el.updateComplete; // safari takes a little longer
|
||||
expect(_listboxNode.hasAttribute('autofocus')).to.be.false;
|
||||
});
|
||||
|
||||
it('adds focus to element with [role=listbox] when trapsKeyboardFocus is true', async () => {
|
||||
const el = await fixture(
|
||||
html` <lion-select-rich .config=${{ trapsKeyboardFocus: true }}></lion-select-rich> `,
|
||||
);
|
||||
const { _listboxNode } = getSelectRichMembers(el);
|
||||
expect(document.activeElement).to.not.equal(_listboxNode);
|
||||
|
||||
el.opened = true;
|
||||
await el.updateComplete;
|
||||
expect(document.activeElement).to.equal(_listboxNode);
|
||||
|
||||
el.opened = false;
|
||||
await el.updateComplete;
|
||||
await el.updateComplete; // safari takes a little longer
|
||||
expect(document.activeElement).to.not.equal(_listboxNode);
|
||||
});
|
||||
});
|
||||
|
||||
describe('interaction-mode', () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue