Skip to content

Commit 03e6600

Browse files
committed
fix(chips): support focusing first/last item using home/end
Based on the accessibility guidelines, grid cells should support moving focus to the first/last items via the Home and End keys.
1 parent c276e26 commit 03e6600

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed

src/lib/chips/chip-list.spec.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
import {FocusKeyManager} from '@angular/cdk/a11y';
22
import {Directionality, Direction} from '@angular/cdk/bidi';
3-
import {BACKSPACE, DELETE, ENTER, LEFT_ARROW, RIGHT_ARROW, SPACE, TAB} from '@angular/cdk/keycodes';
3+
import {
4+
BACKSPACE,
5+
DELETE,
6+
ENTER,
7+
LEFT_ARROW,
8+
RIGHT_ARROW,
9+
SPACE,
10+
TAB,
11+
HOME,
12+
END,
13+
} from '@angular/cdk/keycodes';
414
import {createKeyboardEvent, dispatchFakeEvent, dispatchKeyboardEvent} from '@angular/cdk/testing';
515
import {
616
Component,
@@ -226,6 +236,36 @@ describe('MatChipList', () => {
226236
.toBe(initialActiveIndex, 'Expected focused item not to have changed.');
227237
});
228238

239+
it('should focus the first item when pressing HOME', () => {
240+
const nativeChips = chipListNativeElement.querySelectorAll('mat-chip');
241+
const lastNativeChip = nativeChips[nativeChips.length - 1] as HTMLElement;
242+
const HOME_EVENT = createKeyboardEvent('keydown', HOME, lastNativeChip);
243+
const array = chips.toArray();
244+
const lastItem = array[array.length - 1];
245+
246+
lastItem.focus();
247+
expect(manager.activeItemIndex).toBe(array.length - 1);
248+
249+
chipListInstance._keydown(HOME_EVENT);
250+
fixture.detectChanges();
251+
252+
expect(manager.activeItemIndex).toBe(0);
253+
expect(HOME_EVENT.defaultPrevented).toBe(true);
254+
});
255+
256+
it('should focus the last item when pressing END', () => {
257+
const nativeChips = chipListNativeElement.querySelectorAll('mat-chip');
258+
const END_EVENT = createKeyboardEvent('keydown', END, nativeChips[0]);
259+
260+
expect(manager.activeItemIndex).toBe(-1);
261+
262+
chipListInstance._keydown(END_EVENT);
263+
fixture.detectChanges();
264+
265+
expect(manager.activeItemIndex).toBe(chips.length - 1);
266+
expect(END_EVENT.defaultPrevented).toBe(true);
267+
});
268+
229269
});
230270

231271
describe('RTL', () => {

src/lib/chips/chip-list.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {FocusKeyManager} from '@angular/cdk/a11y';
1010
import {Directionality} from '@angular/cdk/bidi';
1111
import {coerceBooleanProperty} from '@angular/cdk/coercion';
1212
import {SelectionModel} from '@angular/cdk/collections';
13-
import {BACKSPACE} from '@angular/cdk/keycodes';
13+
import {BACKSPACE, HOME, END} from '@angular/cdk/keycodes';
1414
import {
1515
AfterContentInit,
1616
ChangeDetectionStrategy,
@@ -473,7 +473,16 @@ export class MatChipList extends _MatChipListMixinBase implements MatFormFieldCo
473473
this._keyManager.setLastItemActive();
474474
event.preventDefault();
475475
} else if (target && target.classList.contains('mat-chip')) {
476-
this._keyManager.onKeydown(event);
476+
if (event.keyCode === HOME) {
477+
this._keyManager.setFirstItemActive();
478+
event.preventDefault();
479+
} else if (event.keyCode === END) {
480+
this._keyManager.setLastItemActive();
481+
event.preventDefault();
482+
} else {
483+
this._keyManager.onKeydown(event);
484+
}
485+
477486
this.stateChanges.next();
478487
}
479488
}

0 commit comments

Comments
 (0)