From 70638aad9d386df340668ae59558e0260cfa024f Mon Sep 17 00:00:00 2001 From: crisbeto Date: Wed, 21 Nov 2018 22:57:13 +0100 Subject: [PATCH] fix(tabs): don't handle keyboard events with modifier keys Doesn't `preventDefault` or react to any of the keyboard shortcuts, if the user is holding a modifier key, in order to avoid interfering with other OS-level shortcuts. --- src/lib/tabs/tab-header.spec.ts | 31 ++++++++++++++++++++++++++++++- src/lib/tabs/tab-header.ts | 7 ++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/lib/tabs/tab-header.spec.ts b/src/lib/tabs/tab-header.spec.ts index b5aaa2a08485..f30bc970a624 100644 --- a/src/lib/tabs/tab-header.spec.ts +++ b/src/lib/tabs/tab-header.spec.ts @@ -2,7 +2,12 @@ import {Direction, Directionality} from '@angular/cdk/bidi'; import {END, ENTER, HOME, LEFT_ARROW, RIGHT_ARROW, SPACE} from '@angular/cdk/keycodes'; import {PortalModule} from '@angular/cdk/portal'; import {ScrollingModule, ViewportRuler} from '@angular/cdk/scrolling'; -import {dispatchFakeEvent, dispatchKeyboardEvent} from '@angular/cdk/testing'; +import { + dispatchFakeEvent, + dispatchKeyboardEvent, + createKeyboardEvent, + dispatchEvent, +} from '@angular/cdk/testing'; import {CommonModule} from '@angular/common'; import {Component, ViewChild} from '@angular/core'; import { @@ -193,6 +198,30 @@ describe('MatTabHeader', () => { expect(appComponent.tabHeader.focusIndex).toBe(2); }); + it('should not do anything if a modifier key is pressed', () => { + const rightArrowEvent = createKeyboardEvent('keydown', RIGHT_ARROW); + const enterEvent = createKeyboardEvent('keydown', ENTER); + + [rightArrowEvent, enterEvent].forEach(event => { + Object.defineProperty(event, 'shiftKey', {get: () => true}); + }); + + appComponent.tabHeader.focusIndex = 0; + fixture.detectChanges(); + expect(appComponent.tabHeader.focusIndex).toBe(0); + + dispatchEvent(tabListContainer, rightArrowEvent); + fixture.detectChanges(); + expect(appComponent.tabHeader.focusIndex).toBe(0); + expect(rightArrowEvent.defaultPrevented).toBe(false); + + expect(appComponent.selectedIndex).toBe(0); + dispatchEvent(tabListContainer, enterEvent); + fixture.detectChanges(); + expect(appComponent.selectedIndex).toBe(0); + expect(enterEvent.defaultPrevented).toBe(false); + }); + }); describe('pagination', () => { diff --git a/src/lib/tabs/tab-header.ts b/src/lib/tabs/tab-header.ts index 30273380c201..541fe1916f40 100644 --- a/src/lib/tabs/tab-header.ts +++ b/src/lib/tabs/tab-header.ts @@ -8,7 +8,7 @@ import {Direction, Directionality} from '@angular/cdk/bidi'; import {coerceNumberProperty} from '@angular/cdk/coercion'; -import {END, ENTER, HOME, SPACE} from '@angular/cdk/keycodes'; +import {END, ENTER, HOME, SPACE, hasModifierKey} from '@angular/cdk/keycodes'; import {ViewportRuler} from '@angular/cdk/scrolling'; import { AfterContentChecked, @@ -172,6 +172,11 @@ export class MatTabHeader extends _MatTabHeaderMixinBase } _handleKeydown(event: KeyboardEvent) { + // We don't handle any key bindings with a modifier key. + if (hasModifierKey(event)) { + return; + } + switch (event.keyCode) { case HOME: this._keyManager.setFirstItemActive();