Skip to content

Commit 5ec7b83

Browse files
fix: ensure menu-bar is focusable after closing and moving focus (#10273) (#10276)
Co-authored-by: Serhii Kulykov <iamkulykov@gmail.com>
1 parent 030f190 commit 5ec7b83

File tree

4 files changed

+58
-3
lines changed

4 files changed

+58
-3
lines changed

packages/a11y-base/src/keyboard-direction-mixin.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,12 @@ export const KeyboardDirectionMixin = (superclass) =>
104104
if (
105105
this._tabNavigation &&
106106
key === 'Tab' &&
107-
((idx > currentIdx && event.shiftKey) || (idx < currentIdx && !event.shiftKey))
107+
((idx > currentIdx && event.shiftKey) || (idx < currentIdx && !event.shiftKey) || idx === currentIdx)
108108
) {
109109
// Prevent "roving tabindex" logic and let the normal Tab behavior if
110110
// - currently on the first focusable item and Shift + Tab is pressed,
111-
// - currently on the last focusable item and Tab is pressed.
111+
// - currently on the last focusable item and Tab is pressed,
112+
// - currently on the only focusable item and Tab is pressed
112113
return;
113114
}
114115

packages/a11y-base/test/keyboard-direction-mixin.test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,18 @@ const runTests = (defineHelper, baseMixin) => {
245245
tabKeyDown(items[5]);
246246
expect(element.focused).to.not.equal(items[0]);
247247
});
248+
249+
it('should not prevent default on Tab keydown with only one item present', () => {
250+
element.innerHTML = '<div tabindex="0">Foo</div>';
251+
items = element.children;
252+
items[0].focus();
253+
254+
const spy = sinon.spy();
255+
element.addEventListener('keydown', spy);
256+
tabKeyDown(items[0]);
257+
258+
expect(spy.firstCall.args[0].defaultPrevented).to.be.false;
259+
});
248260
});
249261
};
250262

packages/menu-bar/src/vaadin-menu-bar-mixin.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,8 @@ export const MenuBarMixin = (superClass) =>
780780
*/
781781
_setFocused(focused) {
782782
if (focused) {
783-
const target = this.tabNavigation ? this.querySelector('[focused]') : this.querySelector('[tabindex="0"]');
783+
const selector = this.tabNavigation ? '[focused]' : '[tabindex="0"]';
784+
const target = this.querySelector(`vaadin-menu-bar-button${selector}`);
784785
if (target) {
785786
this._buttons.forEach((btn) => {
786787
this._setTabindex(btn, btn === target);

packages/menu-bar/test/keyboard-navigation.test.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,4 +455,45 @@ describe('keyboard navigation', () => {
455455
});
456456
});
457457
});
458+
459+
describe('single button', () => {
460+
beforeEach(async () => {
461+
menu.items = [{ text: 'Item 1', children: [{ text: 'Item 1 1' }] }];
462+
await nextUpdate(menu);
463+
buttons = menu._buttons;
464+
firstGlobalFocusable.focus();
465+
});
466+
467+
it('should be focusable on Shift + Tab after closing and moving focus by default', async () => {
468+
await sendKeys({ press: 'Tab' });
469+
470+
await sendKeys({ press: 'ArrowDown' });
471+
await nextRender();
472+
473+
await sendKeys({ press: 'Escape' });
474+
475+
await sendKeys({ press: 'Tab' });
476+
expect(document.activeElement).to.equal(lastGlobalFocusable);
477+
478+
await sendKeys({ press: 'Shift+Tab' });
479+
expect(document.activeElement).to.equal(buttons[0]);
480+
});
481+
482+
it('should be focusable on Shift + Tab after closing and moving focus with Tab navigation', async () => {
483+
menu.tabNavigation = true;
484+
485+
await sendKeys({ press: 'Tab' });
486+
487+
await sendKeys({ press: 'ArrowDown' });
488+
await nextRender();
489+
490+
await sendKeys({ press: 'Escape' });
491+
492+
await sendKeys({ press: 'Tab' });
493+
expect(document.activeElement).to.equal(lastGlobalFocusable);
494+
495+
await sendKeys({ press: 'Shift+Tab' });
496+
expect(document.activeElement).to.equal(buttons[0]);
497+
});
498+
});
458499
});

0 commit comments

Comments
 (0)