Skip to content

Commit a8355e4

Browse files
crisbetotinayuangao
authored andcommitted
fix(list-key-manager): prevent the default keyboard actions (#2009)
Calls preventDefault when handling keyboard events in the ListKeyManager. This avoids the user scrolling the page when using the arrow keys to navigate. Relates to #1999.
1 parent b36db15 commit a8355e4

File tree

2 files changed

+41
-6
lines changed

2 files changed

+41
-6
lines changed

src/lib/core/a11y/list-key-manager.spec.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,23 @@ class FakeQueryList<T> extends QueryList<T> {
1515
}
1616
}
1717

18-
const DOWN_ARROW_EVENT = { keyCode: DOWN_ARROW } as KeyboardEvent;
19-
const UP_ARROW_EVENT = { keyCode: UP_ARROW } as KeyboardEvent;
20-
const TAB_EVENT = { keyCode: TAB } as KeyboardEvent;
21-
const HOME_EVENT = { keyCode: HOME } as KeyboardEvent;
22-
const END_EVENT = { keyCode: END } as KeyboardEvent;
18+
class FakeEvent {
19+
defaultPrevented: boolean = false;
20+
constructor(public keyCode: number) {}
21+
preventDefault() {
22+
this.defaultPrevented = true;
23+
}
24+
}
25+
2326

2427
describe('ListKeyManager', () => {
2528
let keyManager: ListKeyManager;
2629
let itemList: FakeQueryList<FakeFocusable>;
30+
let DOWN_ARROW_EVENT: KeyboardEvent;
31+
let UP_ARROW_EVENT: KeyboardEvent;
32+
let TAB_EVENT: KeyboardEvent;
33+
let HOME_EVENT: KeyboardEvent;
34+
let END_EVENT: KeyboardEvent;
2735

2836
beforeEach(() => {
2937
itemList = new FakeQueryList<FakeFocusable>();
@@ -35,6 +43,12 @@ describe('ListKeyManager', () => {
3543

3644
keyManager = new ListKeyManager(itemList);
3745

46+
DOWN_ARROW_EVENT = new FakeEvent(DOWN_ARROW) as KeyboardEvent;
47+
UP_ARROW_EVENT = new FakeEvent(UP_ARROW) as KeyboardEvent;
48+
TAB_EVENT = new FakeEvent(TAB) as KeyboardEvent;
49+
HOME_EVENT = new FakeEvent(HOME) as KeyboardEvent;
50+
END_EVENT = new FakeEvent(END) as KeyboardEvent;
51+
3852
// first item is already focused
3953
keyManager.focusFirstItem();
4054

@@ -166,6 +180,22 @@ describe('ListKeyManager', () => {
166180
expect(tabOutEmitted).toBe(true);
167181
});
168182

183+
it('should prevent the default keyboard action', () => {
184+
expect(DOWN_ARROW_EVENT.defaultPrevented).toBe(false);
185+
186+
keyManager.onKeydown(DOWN_ARROW_EVENT);
187+
188+
expect(DOWN_ARROW_EVENT.defaultPrevented).toBe(true);
189+
});
190+
191+
it('should not prevent the default keyboard action when pressing tab', () => {
192+
expect(TAB_EVENT.defaultPrevented).toBe(false);
193+
194+
keyManager.onKeydown(TAB_EVENT);
195+
196+
expect(TAB_EVENT.defaultPrevented).toBe(false);
197+
});
198+
169199
});
170200

171201
describe('programmatic focus', () => {

src/lib/core/a11y/list-key-manager.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,14 @@ export class ListKeyManager {
5454
this.focusLastItem();
5555
break;
5656
case TAB:
57+
// Note that we shouldn't prevent the default action on tab.
5758
this._tabOut.next(null);
58-
break;
59+
return;
60+
default:
61+
return;
5962
}
63+
64+
event.preventDefault();
6065
}
6166

6267
/** Focuses the first enabled item in the list. */

0 commit comments

Comments
 (0)