From 834aecce64dcd13fe37541b010ee21c6ede60382 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 1 Feb 2018 20:24:31 +0100 Subject: [PATCH] fix(stepper): support going to first/last steps via home/end keys (#9632) Adds support for the user to skip to the first/last step in the stepper using the home and end keys. [Based on the a11y guidelines](https://www.w3.org/TR/wai-aria-practices-1.1/#tabpanel). --- src/cdk/stepper/stepper.ts | 21 ++++++++++++++++++++- src/lib/stepper/stepper.spec.ts | 21 ++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/cdk/stepper/stepper.ts b/src/cdk/stepper/stepper.ts index e4d1c0939fd..03900c5841b 100644 --- a/src/cdk/stepper/stepper.ts +++ b/src/cdk/stepper/stepper.ts @@ -27,7 +27,16 @@ import { OnChanges, OnDestroy } from '@angular/core'; -import {LEFT_ARROW, RIGHT_ARROW, DOWN_ARROW, UP_ARROW, ENTER, SPACE} from '@angular/cdk/keycodes'; +import { + LEFT_ARROW, + RIGHT_ARROW, + DOWN_ARROW, + UP_ARROW, + ENTER, + SPACE, + HOME, + END, +} from '@angular/cdk/keycodes'; import {CdkStepLabel} from './step-label'; import {coerceBooleanProperty} from '@angular/cdk/coercion'; import {AbstractControl} from '@angular/forms'; @@ -307,6 +316,16 @@ export class CdkStepper implements OnDestroy { this.selectedIndex = this._focusIndex; event.preventDefault(); } + + if (keyCode === HOME) { + this._focusStep(0); + event.preventDefault(); + } + + if (keyCode === END) { + this._focusStep(this._steps.length - 1); + event.preventDefault(); + } } private _focusNextStep() { diff --git a/src/lib/stepper/stepper.spec.ts b/src/lib/stepper/stepper.spec.ts index 8f13b9609d3..775a50faa2b 100644 --- a/src/lib/stepper/stepper.spec.ts +++ b/src/lib/stepper/stepper.spec.ts @@ -1,5 +1,14 @@ import {Directionality} from '@angular/cdk/bidi'; -import {ENTER, LEFT_ARROW, RIGHT_ARROW, UP_ARROW, DOWN_ARROW, SPACE} from '@angular/cdk/keycodes'; +import { + ENTER, + LEFT_ARROW, + RIGHT_ARROW, + UP_ARROW, + DOWN_ARROW, + SPACE, + HOME, + END, +} from '@angular/cdk/keycodes'; import {dispatchKeyboardEvent} from '@angular/cdk/testing'; import {Component, DebugElement} from '@angular/core'; import {async, ComponentFixture, TestBed, inject} from '@angular/core/testing'; @@ -725,6 +734,16 @@ function assertCorrectKeyboardInteraction(fixture: ComponentFixture, expect(stepperComponent.selectedIndex) .toBe(0, 'Expected index of selected step to change to index of focused step after SPACE event.'); + + const endEvent = dispatchKeyboardEvent(stepHeaderEl, 'keydown', END); + expect(stepperComponent._focusIndex) + .toBe(stepHeaders.length - 1, 'Expected last step to be focused when pressing END.'); + expect(endEvent.defaultPrevented).toBe(true, 'Expected default END action to be prevented.'); + + const homeEvent = dispatchKeyboardEvent(stepHeaderEl, 'keydown', HOME); + expect(stepperComponent._focusIndex) + .toBe(0, 'Expected first step to be focused when pressing HOME.'); + expect(homeEvent.defaultPrevented).toBe(true, 'Expected default HOME action to be prevented.'); } /** Asserts that step selection change using stepper buttons does not focus step header. */