From 2fbb81daa030945ec4ef433f1f9212894565da7a Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Sat, 10 Jun 2023 20:15:37 +0200 Subject: [PATCH] fix(material/tabs): prevent default keyboard actions on disabled links (#27274) Fixes that while we were preventing clicks on disabled links using `pointer-events`, we didn't prevent keyboard events. Fixes #27270. --- .../tabs/tab-nav-bar/tab-nav-bar.spec.ts | 41 +++++++------------ src/material/tabs/tab-nav-bar/tab-nav-bar.ts | 6 ++- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/material/tabs/tab-nav-bar/tab-nav-bar.spec.ts b/src/material/tabs/tab-nav-bar/tab-nav-bar.spec.ts index d30951ef920f..444c290ffa96 100644 --- a/src/material/tabs/tab-nav-bar/tab-nav-bar.spec.ts +++ b/src/material/tabs/tab-nav-bar/tab-nav-bar.spec.ts @@ -1,4 +1,4 @@ -import {SPACE} from '@angular/cdk/keycodes'; +import {ENTER, SPACE} from '@angular/cdk/keycodes'; import {waitForAsync, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'; import {Component, QueryList, ViewChild, ViewChildren} from '@angular/core'; import {MAT_RIPPLE_GLOBAL_OPTIONS, RippleGlobalOptions} from '@angular/material/core'; @@ -73,31 +73,6 @@ describe('MDC-based MatTabNavBar', () => { expect(tabLinkElements[1].classList.contains('mdc-tab--active')).toBeTruthy(); }); - it('should add the disabled class if disabled', () => { - const tabLinkElements = fixture.debugElement - .queryAll(By.css('a')) - .map(tabLinkDebugEl => tabLinkDebugEl.nativeElement); - - expect( - tabLinkElements.every(tabLinkEl => { - return !tabLinkEl.classList.contains('mat-mdc-tab-disabled'); - }), - ) - .withContext('Expected every tab link to not have the disabled class initially') - .toBe(true); - - fixture.componentInstance.disabled = true; - fixture.detectChanges(); - - expect( - tabLinkElements.every(tabLinkEl => { - return tabLinkEl.classList.contains('mat-mdc-tab-disabled'); - }), - ) - .withContext('Expected every tab link to have the disabled class if set through binding') - .toBe(true); - }); - it('should update aria-disabled if disabled', () => { const tabLinkElements = fixture.debugElement .queryAll(By.css('a')) @@ -143,6 +118,20 @@ describe('MDC-based MatTabNavBar', () => { expect(tabLinkElement.classList).toContain('mat-mdc-tab-disabled'); }); + it('should prevent default keyboard actions on disabled links', () => { + const link = fixture.debugElement.query(By.css('a')).nativeElement; + fixture.componentInstance.disabled = true; + fixture.detectChanges(); + + const spaceEvent = dispatchKeyboardEvent(link, 'keydown', SPACE); + fixture.detectChanges(); + expect(spaceEvent.defaultPrevented).toBe(true); + + const enterEvent = dispatchKeyboardEvent(link, 'keydown', ENTER); + fixture.detectChanges(); + expect(enterEvent.defaultPrevented).toBe(true); + }); + it('should re-align the ink bar when the direction changes', fakeAsync(() => { const inkBar = fixture.componentInstance.tabNavBar._inkBar; diff --git a/src/material/tabs/tab-nav-bar/tab-nav-bar.ts b/src/material/tabs/tab-nav-bar/tab-nav-bar.ts index ba64e94cc3f6..73389ec1ca11 100644 --- a/src/material/tabs/tab-nav-bar/tab-nav-bar.ts +++ b/src/material/tabs/tab-nav-bar/tab-nav-bar.ts @@ -48,7 +48,7 @@ import {MatInkBar, MatInkBarItem, mixinInkBarItem} from '../ink-bar'; import {BooleanInput, coerceBooleanProperty, NumberInput} from '@angular/cdk/coercion'; import {BehaviorSubject, Subject} from 'rxjs'; import {startWith, takeUntil} from 'rxjs/operators'; -import {SPACE} from '@angular/cdk/keycodes'; +import {ENTER, SPACE} from '@angular/cdk/keycodes'; import {MAT_TABS_CONFIG, MatTabsConfig} from '../tab-config'; import {MatPaginatedTabHeader, MatPaginatedTabHeaderItem} from '../paginated-tab-header'; @@ -261,7 +261,9 @@ export class _MatTabLinkBase } _handleKeydown(event: KeyboardEvent) { - if (this._tabNavBar.tabPanel && event.keyCode === SPACE) { + if (this.disabled && (event.keyCode === SPACE || event.keyCode === ENTER)) { + event.preventDefault(); + } else if (this._tabNavBar.tabPanel && event.keyCode === SPACE) { this.elementRef.nativeElement.click(); } }