Skip to content

Commit f38b082

Browse files
committed
fix(a11y): don't handle disallowed modifier keys in typeahead mode
Recently we switched to skip handling keyboard events with modifiers, unless the consumer opted into them explicitly. The changes weren't applied when in typeahead mode. Fixes #14274.
1 parent 141afcf commit f38b082

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

src/cdk/a11y/key-manager/list-key-manager.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,30 @@ describe('Key managers', () => {
664664
expect(keyManager.activeItem).toBe(itemList.items[1]);
665665
}));
666666

667+
it('should not move focus if a modifier, that is not allowed, is pressed', fakeAsync(() => {
668+
const tEvent = createKeyboardEvent('keydown', 84, undefined, 't');
669+
Object.defineProperty(tEvent, 'ctrlKey', {get: () => true});
670+
671+
expect(keyManager.activeItem).toBeFalsy();
672+
673+
keyManager.onKeydown(tEvent); // types "t"
674+
tick(debounceInterval);
675+
676+
expect(keyManager.activeItem).toBeFalsy();
677+
}));
678+
679+
it('should always allow the shift key', fakeAsync(() => {
680+
const tEvent = createKeyboardEvent('keydown', 84, undefined, 't');
681+
Object.defineProperty(tEvent, 'shiftKey', {get: () => true});
682+
683+
expect(keyManager.activeItem).toBeFalsy();
684+
685+
keyManager.onKeydown(tEvent); // types "t"
686+
tick(debounceInterval);
687+
688+
expect(keyManager.activeItem).toBeTruthy();
689+
}));
690+
667691
it('should focus the first item that starts with sequence of letters', fakeAsync(() => {
668692
keyManager.onKeydown(createKeyboardEvent('keydown', 84, undefined, 't')); // types "t"
669693
keyManager.onKeydown(createKeyboardEvent('keydown', 72, undefined, 'h')); // types "h"

src/cdk/a11y/key-manager/list-key-manager.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
Z,
1919
ZERO,
2020
NINE,
21+
hasModifierKey,
2122
} from '@angular/cdk/keycodes';
2223
import {debounceTime, filter, map, tap} from 'rxjs/operators';
2324

@@ -244,12 +245,14 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
244245
}
245246

246247
default:
247-
// Attempt to use the `event.key` which also maps it to the user's keyboard language,
248-
// otherwise fall back to resolving alphanumeric characters via the keyCode.
249-
if (event.key && event.key.length === 1) {
250-
this._letterKeyStream.next(event.key.toLocaleUpperCase());
251-
} else if ((keyCode >= A && keyCode <= Z) || (keyCode >= ZERO && keyCode <= NINE)) {
252-
this._letterKeyStream.next(String.fromCharCode(keyCode));
248+
if (isModifierAllowed || hasModifierKey(event, 'shiftKey')) {
249+
// Attempt to use the `event.key` which also maps it to the user's keyboard language,
250+
// otherwise fall back to resolving alphanumeric characters via the keyCode.
251+
if (event.key && event.key.length === 1) {
252+
this._letterKeyStream.next(event.key.toLocaleUpperCase());
253+
} else if ((keyCode >= A && keyCode <= Z) || (keyCode >= ZERO && keyCode <= NINE)) {
254+
this._letterKeyStream.next(String.fromCharCode(keyCode));
255+
}
253256
}
254257

255258
// Note that we return here, in order to avoid preventing

0 commit comments

Comments
 (0)