@@ -18,7 +18,7 @@ import { IThemeService, IColorTheme } from 'vs/platform/theme/common/themeServic
1818import { ACTIVITY_BAR_BACKGROUND , ACTIVITY_BAR_BORDER , ACTIVITY_BAR_FOREGROUND , ACTIVITY_BAR_ACTIVE_BORDER , ACTIVITY_BAR_BADGE_BACKGROUND , ACTIVITY_BAR_BADGE_FOREGROUND , ACTIVITY_BAR_INACTIVE_FOREGROUND , ACTIVITY_BAR_ACTIVE_BACKGROUND , ACTIVITY_BAR_DRAG_AND_DROP_BORDER } from 'vs/workbench/common/theme' ;
1919import { contrastBorder } from 'vs/platform/theme/common/colorRegistry' ;
2020import { CompositeBar , ICompositeBarItem , CompositeDragAndDrop } from 'vs/workbench/browser/parts/compositeBar' ;
21- import { Dimension , addClass , removeNode , createCSSRule , asCSSUrl , toggleClass } from 'vs/base/browser/dom' ;
21+ import { Dimension , addClass , removeNode , createCSSRule , asCSSUrl , toggleClass , addDisposableListener , EventType } from 'vs/base/browser/dom' ;
2222import { IStorageService , StorageScope , IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage' ;
2323import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions' ;
2424import { URI , UriComponents } from 'vs/base/common/uri' ;
@@ -39,6 +39,8 @@ import { Before2D } from 'vs/workbench/browser/dnd';
3939import { Codicon , iconRegistry } from 'vs/base/common/codicons' ;
4040import { Action } from 'vs/base/common/actions' ;
4141import { Event } from 'vs/base/common/event' ;
42+ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent' ;
43+ import { KeyCode } from 'vs/base/common/keyCodes' ;
4244
4345interface IPlaceholderViewContainer {
4446 id : string ;
@@ -92,16 +94,20 @@ export class ActivitybarPart extends Part implements IActivityBarService {
9294 private menuBarContainer : HTMLElement | undefined ;
9395
9496 private compositeBar : CompositeBar ;
97+ private compositeBarContainer : HTMLElement | undefined ;
9598
9699 private globalActivityAction : ActivityAction | undefined ;
97100 private globalActivityActionBar : ActionBar | undefined ;
98101 private readonly globalActivity : ICompositeActivity [ ] = [ ] ;
102+ private globalActivitiesContainer : HTMLElement | undefined ;
99103
100104 private accountsActivityAction : ActivityAction | undefined ;
101105
102106 private readonly compositeActions = new Map < string , { activityAction : ViewContainerActivityAction , pinnedAction : ToggleCompositePinnedAction } > ( ) ;
103107 private readonly viewContainerDisposables = new Map < string , IDisposable > ( ) ;
104108
109+ private readonly keyboardNavigationDisposables = new DisposableStore ( ) ;
110+
105111 private readonly location = ViewContainerLocation . Sidebar ;
106112
107113 constructor (
@@ -136,6 +142,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
136142 this . compositeBar = this . _register ( this . instantiationService . createInstance ( CompositeBar , cachedItems , {
137143 icon : true ,
138144 orientation : ActionsOrientation . VERTICAL ,
145+ preventLoopNavigation : true ,
139146 openComposite : ( compositeId : string ) => this . viewsService . openViewContainer ( compositeId , true ) ,
140147 getActivityAction : ( compositeId : string ) => this . getCompositeActions ( compositeId ) . activityAction ,
141148 getCompositePinnedAction : ( compositeId : string ) => this . getCompositeActions ( compositeId ) . pinnedAction ,
@@ -375,10 +382,13 @@ export class ActivitybarPart extends Part implements IActivityBarService {
375382 private uninstallMenubar ( ) {
376383 if ( this . menuBar ) {
377384 this . menuBar . dispose ( ) ;
385+ this . menuBar = undefined ;
378386 }
379387
380388 if ( this . menuBarContainer ) {
381389 removeNode ( this . menuBarContainer ) ;
390+ this . menuBarContainer = undefined ;
391+ this . registerKeyboardNavigationListeners ( ) ;
382392 }
383393 }
384394
@@ -392,6 +402,8 @@ export class ActivitybarPart extends Part implements IActivityBarService {
392402 // Menubar: install a custom menu bar depending on configuration
393403 this . menuBar = this . _register ( this . instantiationService . createInstance ( CustomMenubarControl ) ) ;
394404 this . menuBar . create ( this . menuBarContainer ) ;
405+
406+ this . registerKeyboardNavigationListeners ( ) ;
395407 }
396408
397409 createContentArea ( parent : HTMLElement ) : HTMLElement {
@@ -420,18 +432,87 @@ export class ActivitybarPart extends Part implements IActivityBarService {
420432 }
421433
422434 // View Containers action bar
423- this . compositeBar . create ( this . content ) ;
435+ this . compositeBarContainer = this . compositeBar . create ( this . content ) ;
424436
425437 // Global action bar
426- const globalActivities = document . createElement ( 'div' ) ;
427- addClass ( globalActivities , 'global-activity' ) ;
428- this . content . appendChild ( globalActivities ) ;
438+ this . globalActivitiesContainer = document . createElement ( 'div' ) ;
439+ addClass ( this . globalActivitiesContainer , 'global-activity' ) ;
440+ this . content . appendChild ( this . globalActivitiesContainer ) ;
429441
430- this . createGlobalActivityActionBar ( globalActivities ) ;
442+ this . createGlobalActivityActionBar ( this . globalActivitiesContainer ) ;
443+
444+ this . registerKeyboardNavigationListeners ( ) ;
431445
432446 return this . content ;
433447 }
434448
449+ private registerKeyboardNavigationListeners ( ) : void {
450+ this . keyboardNavigationDisposables . clear ( ) ;
451+
452+ // Down arrow on home indicator
453+ if ( this . homeBarContainer ) {
454+ this . keyboardNavigationDisposables . add ( addDisposableListener ( this . homeBarContainer , EventType . KEY_DOWN , e => {
455+ const kbEvent = new StandardKeyboardEvent ( e ) ;
456+ if ( kbEvent . equals ( KeyCode . DownArrow ) ) {
457+ if ( this . menuBar ) {
458+ this . menuBar . toggleFocus ( ) ;
459+ } else if ( this . compositeBar ) {
460+ this . compositeBar . focus ( ) ;
461+ }
462+ }
463+ } ) ) ;
464+ }
465+
466+ // Up/Down arrow on compact menu
467+ if ( this . menuBarContainer ) {
468+ this . keyboardNavigationDisposables . add ( addDisposableListener ( this . menuBarContainer , EventType . KEY_DOWN , e => {
469+ const kbEvent = new StandardKeyboardEvent ( e ) ;
470+ if ( kbEvent . equals ( KeyCode . DownArrow ) ) {
471+ if ( this . compositeBar ) {
472+ this . compositeBar . focus ( ) ;
473+ }
474+ } else if ( kbEvent . equals ( KeyCode . UpArrow ) ) {
475+ if ( this . homeBar ) {
476+ this . homeBar . focus ( ) ;
477+ }
478+ }
479+ } ) ) ;
480+ }
481+
482+ // Up/Down on Activity Icons
483+ if ( this . compositeBarContainer ) {
484+ this . keyboardNavigationDisposables . add ( addDisposableListener ( this . compositeBarContainer , EventType . KEY_DOWN , e => {
485+ const kbEvent = new StandardKeyboardEvent ( e ) ;
486+ if ( kbEvent . equals ( KeyCode . DownArrow ) ) {
487+ if ( this . globalActivityActionBar ) {
488+ this . globalActivityActionBar . focus ( true ) ;
489+ }
490+ } else if ( kbEvent . equals ( KeyCode . UpArrow ) ) {
491+ if ( this . menuBar ) {
492+ this . menuBar . toggleFocus ( ) ;
493+ } else if ( this . homeBar ) {
494+ this . homeBar . focus ( ) ;
495+ }
496+ }
497+ } ) ) ;
498+ }
499+
500+ // Up arrow on global icons
501+ if ( this . globalActivitiesContainer ) {
502+ this . keyboardNavigationDisposables . add ( addDisposableListener ( this . globalActivitiesContainer , EventType . KEY_DOWN , e => {
503+ const kbEvent = new StandardKeyboardEvent ( e ) ;
504+ if ( kbEvent . equals ( KeyCode . UpArrow ) ) {
505+ if ( this . compositeBar ) {
506+ this . compositeBar . focus ( this . getVisibleViewContainerIds ( ) . length - 1 ) ;
507+ }
508+ }
509+ } ) ) ;
510+ }
511+
512+
513+
514+ }
515+
435516 private createHomeBar ( href : string , title : string , icon : Codicon ) : void {
436517 this . homeBarContainer = document . createElement ( 'div' ) ;
437518 this . homeBarContainer . setAttribute ( 'aria-label' , nls . localize ( 'homeIndicator' , "Home" ) ) ;
@@ -443,7 +524,8 @@ export class ActivitybarPart extends Part implements IActivityBarService {
443524 animated : false ,
444525 ariaLabel : nls . localize ( 'home' , "Home" ) ,
445526 actionViewItemProvider : action => new HomeActionViewItem ( action ) ,
446- allowContextMenu : true
527+ allowContextMenu : true ,
528+ preventLoopNavigation : true
447529 } ) ) ;
448530
449531 const homeBarIconBadge = document . createElement ( 'div' ) ;
@@ -495,7 +577,8 @@ export class ActivitybarPart extends Part implements IActivityBarService {
495577 } ,
496578 orientation : ActionsOrientation . VERTICAL ,
497579 ariaLabel : nls . localize ( 'manage' , "Manage" ) ,
498- animated : false
580+ animated : false ,
581+ preventLoopNavigation : true
499582 } ) ) ;
500583
501584 this . globalActivityAction = new ActivityAction ( {
0 commit comments