11<template >
2- <div
3- class =" header-navigation"
4- >
5- <div class =" header-navigation__main" >
2+ <div class =" header-navigation" >
3+ <div class =" sf-header-navigation-item__item sf-header-navigation-item__item--desktop" >
64 <HeaderNavigationItem
75 v-for =" (category, index) in categoryTree"
86 :key =" index"
7+ ref =" lvl0CatRefs"
98 :data-testid =" category.uid"
10- class =" nav-item"
119 :label =" category.name"
1210 :link =" localePath(getCatLink(category))"
13- @mouseenter.native =" setCurrentCategory(category)"
14- @keyup.tab.native =" setCurrentCategory(category)"
11+ tabindex =" 1"
12+ aria-haspopup =" true"
13+ class =" nav-item"
14+ :data-index =" index"
15+ :has-children =" hasChildren(category)"
16+ @mouseenter.native.prevent =" onMouseEnter(category)"
17+ @keydown.down.native.prevent =" setCurrentCategory(category)"
18+ @keydown.up.native.prevent =" setCurrentCategory(null)"
19+ @keyup.tab.native.prevent =" setFocus($event)"
20+ @keydown.right.native.prevent =" navRight()"
21+ @keydown.left.native.prevent =" navLeft()"
1522 />
1623 </div >
1724 <HeaderNavigationSubcategories
1825 v-if =" hasChildren(currentCategory)"
1926 :current-category =" currentCategory"
20- @hideSubcategories =" setCurrentCategory(null)"
27+ :has-focus =" hasFocus"
28+ @hideSubcategories =" focusRootElementAndHideSubcategories"
2129 />
2230 </div >
2331</template >
@@ -44,19 +52,68 @@ export default defineComponent({
4452 },
4553 setup() {
4654 const { getCatLink } = useUiHelpers ();
55+
4756 const currentCategory = ref <CategoryTree >(null );
57+ const lvl0CatRefs = ref ([]);
58+ const hasFocus = ref (false );
59+ let lvl0CatFocusIdx = 0 ;
60+ let focusedElement = null ;
4861
4962 const setCurrentCategory = (category : CategoryTree | null ) => {
5063 currentCategory .value = category ;
5164 };
5265
5366 const hasChildren = (category : CategoryTree ) => Boolean (category ?.children );
5467
68+ const setFocus = (event ) => {
69+ focusedElement = event .target ;
70+ lvl0CatFocusIdx = Number (event .target .dataset .index );
71+ hasFocus .value = true ;
72+ };
73+
74+ const focusRootElementAndHideSubcategories = () => {
75+ setCurrentCategory (null );
76+ if (focusedElement !== null ) focusedElement .focus ();
77+ };
78+
79+ const navRight = () => {
80+ lvl0CatFocusIdx ++ ;
81+ if (lvl0CatRefs .value [lvl0CatFocusIdx ]) {
82+ lvl0CatRefs .value [lvl0CatFocusIdx ].$el .focus ();
83+ focusedElement = lvl0CatRefs .value [lvl0CatFocusIdx ].$el ;
84+ } else {
85+ lvl0CatFocusIdx -- ;
86+ }
87+ };
88+
89+ const navLeft = () => {
90+ lvl0CatFocusIdx -- ;
91+ if (lvl0CatRefs .value [lvl0CatFocusIdx ]) {
92+ lvl0CatRefs .value [lvl0CatFocusIdx ].$el .focus ();
93+ focusedElement = lvl0CatRefs .value [lvl0CatFocusIdx ].$el ;
94+ } else {
95+ lvl0CatFocusIdx ++ ;
96+ }
97+ };
98+
99+ const onMouseEnter = (category : CategoryTree ) => {
100+ currentCategory .value = category ;
101+ focusedElement = null ;
102+ hasFocus .value = false ;
103+ };
104+
55105 return {
56106 getCatLink ,
57107 setCurrentCategory ,
58108 currentCategory ,
59109 hasChildren ,
110+ setFocus ,
111+ focusRootElementAndHideSubcategories ,
112+ lvl0CatRefs ,
113+ navRight ,
114+ navLeft ,
115+ hasFocus ,
116+ onMouseEnter ,
60117 };
61118 },
62119});
0 commit comments