This commit is contained in:
Cory LaViska
2022-11-09 09:50:58 -05:00
parent 49193c972f
commit 5fd682d83a
4 changed files with 40 additions and 28 deletions

View File

@@ -284,4 +284,27 @@ describe('<sl-dropdown>', () => {
expect(el.open).to.be.false;
});
it('should close and stop propagating the keydown event when Escape is pressed and the dropdown is open ', async () => {
const el = await fixture<SlDropdown>(html`
<sl-dropdown open>
<sl-button slot="trigger" caret>Toggle</sl-button>
<sl-menu>
<sl-menu-item>Dropdown Item 1</sl-menu-item>
<sl-menu-item>Dropdown Item 2</sl-menu-item>
<sl-menu-item>Dropdown Item 3</sl-menu-item>
</sl-menu>
</sl-dropdown>
`);
const firstMenuItem = el.querySelector('sl-menu-item')!;
const hideHandler = sinon.spy();
document.body.addEventListener('keydown', hideHandler);
firstMenuItem.focus();
await sendKeys({ press: 'Escape' });
await el.updateComplete;
expect(el.open).to.be.false;
expect(hideHandler).to.not.have.been.called;
});
});

View File

@@ -100,6 +100,7 @@ export default class SlDropdown extends ShoelaceElement {
super.connectedCallback();
this.handleMenuItemActivate = this.handleMenuItemActivate.bind(this);
this.handlePanelSelect = this.handlePanelSelect.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleDocumentKeyDown = this.handleDocumentKeyDown.bind(this);
this.handleDocumentMouseDown = this.handleDocumentMouseDown.bind(this);
@@ -139,14 +140,17 @@ export default class SlDropdown extends ShoelaceElement {
| undefined;
}
handleDocumentKeyDown(event: KeyboardEvent) {
// Close when escape is pressed
if (event.key === 'Escape') {
handleKeyDown(event: KeyboardEvent) {
// Close when escape is pressed inside an open dropdown. We need to listen on the panel itself and stop propagation
// in case any ancestors are also listening for this key.
if (this.open && event.key === 'Escape') {
event.stopPropagation();
this.hide();
this.focusOnTrigger();
return;
}
}
handleDocumentKeyDown(event: KeyboardEvent) {
// Handle tabbing
if (event.key === 'Tab') {
// Tabbing within an open menu should close the dropdown and refocus the trigger
@@ -341,6 +345,7 @@ export default class SlDropdown extends ShoelaceElement {
addOpenListeners() {
this.panel.addEventListener('sl-activate', this.handleMenuItemActivate);
this.panel.addEventListener('sl-select', this.handlePanelSelect);
this.panel.addEventListener('keydown', this.handleKeyDown);
document.addEventListener('keydown', this.handleDocumentKeyDown);
document.addEventListener('mousedown', this.handleDocumentMouseDown);
}
@@ -349,6 +354,7 @@ export default class SlDropdown extends ShoelaceElement {
if (this.panel) {
this.panel.removeEventListener('sl-activate', this.handleMenuItemActivate);
this.panel.removeEventListener('sl-select', this.handlePanelSelect);
this.panel.removeEventListener('keydown', this.handleKeyDown);
}
document.removeEventListener('keydown', this.handleDocumentKeyDown);
document.removeEventListener('mousedown', this.handleDocumentMouseDown);