1- import { Component } from "@angular/core" ;
1+ import { Component , ViewChild , HostListener } from "@angular/core" ;
22import { Dialog } from "../dialog.component" ;
33import { position } from "../../utils/position" ;
4+ import { isFocusInLastItem , isFocusInFirstItem } from "./../../common/tab.service" ;
45
56/**
67 * Extend the `Dialog` component to create an overflow menu.
@@ -12,8 +13,7 @@ import { position } from "../../utils/position";
1213 template : `
1314 <ul
1415 #dialog
15- class="bx--overflow-menu-options bx--overflow-menu-options--open"
16- tabindex="-1">
16+ class="bx--overflow-menu-options bx--overflow-menu-options--open">
1717 <ng-template
1818 [ngTemplateOutlet]="dialogConfig.content"
1919 [ngTemplateOutletContext]="{overflowMenu: this}">
@@ -22,6 +22,8 @@ import { position } from "../../utils/position";
2222 `
2323} )
2424export class OverflowMenuPane extends Dialog {
25+ @ViewChild ( "dialog" ) dialog ;
26+
2527 onDialogInit ( ) {
2628 /**
2729 * -20 shifts the menu up to compensate for the
@@ -32,5 +34,61 @@ export class OverflowMenuPane extends Dialog {
3234 * so we need to add some compensation)
3335 */
3436 this . addGap [ "bottom" ] = pos => position . addOffset ( pos , - 20 , 60 ) ;
37+
38+ setTimeout ( ( ) => {
39+ this . listItems ( ) [ 0 ] . focus ( ) ;
40+ } ) ;
41+ }
42+
43+ @HostListener ( "keydown" , [ "$event" ] )
44+ hostkeys ( event : KeyboardEvent ) {
45+ this . escapeClose ( event ) ;
46+ const listItems = this . listItems ( ) ;
47+
48+ switch ( event . key ) {
49+ case "ArrowDown" : {
50+ event . preventDefault ( ) ;
51+ if ( ! isFocusInLastItem ( event , listItems ) ) {
52+ const index = listItems . findIndex ( item => item === event . target ) ;
53+ listItems [ index + 1 ] . focus ( ) ;
54+ } else {
55+ listItems [ 0 ] . focus ( ) ;
56+ }
57+ break ;
58+ }
59+
60+ case "ArrowUp" : {
61+ event . preventDefault ( ) ;
62+ if ( ! isFocusInFirstItem ( event , listItems ) ) {
63+ const index = listItems . findIndex ( item => item === event . target ) ;
64+ listItems [ index - 1 ] . focus ( ) ;
65+ } else {
66+ listItems [ listItems . length - 1 ] . focus ( ) ;
67+ }
68+ break ;
69+ }
70+
71+ case "Home" : {
72+ event . preventDefault ( ) ;
73+ listItems [ 0 ] . focus ( ) ;
74+ break ;
75+ }
76+
77+ case "End" : {
78+ event . preventDefault ( ) ;
79+ listItems [ listItems . length - 1 ] . focus ( ) ;
80+ break ;
81+ }
82+ case "Enter" :
83+ case " " : {
84+ this . doClose ( ) ;
85+ }
86+ }
87+ }
88+
89+ private listItems ( ) {
90+ const buttonClass = ".bx--overflow-menu-options__btn" ;
91+ const disabledClass = ".bx--overflow-menu-options__option--disabled" ;
92+ return Array . prototype . slice . call ( this . dialog . nativeElement . querySelectorAll ( `${ buttonClass } :not(${ disabledClass } )` ) ) ;
3593 }
3694}
0 commit comments