11<template >
22 <div
33 class =" header-navigation"
4+ @mouseleave =" setCurrentCategory(null)"
45 >
56 <div class =" header-navigation__main" >
67 <HeaderNavigationItem
78 v-for =" (category, index) in categoryTree"
89 :key =" index"
10+ ref =" lvl0CatRefs"
911 :data-testid =" category.uid"
10- class =" nav-item"
1112 :label =" category.name"
1213 :link =" localePath(getCatLink(category))"
13- @mouseenter.native =" setCurrentCategory(category)"
14- @keyup.tab.native =" setCurrentCategory(category)"
14+ tabindex =" 0"
15+ aria-haspopup =" true"
16+ class =" nav-item"
17+ :data-index =" index"
18+ :has-children =" hasChildren(category)"
19+ @mouseenter.native.prevent =" onMouseEnter(category)"
20+ @keydown.down.native.prevent =" setCurrentCategory(category)"
21+ @keydown.up.native.prevent =" setCurrentCategory(null)"
22+ @keyup.tab.native.prevent =" setFocus($event)"
23+ @keydown.right.native.prevent =" navRight()"
24+ @keydown.left.native.prevent =" navLeft()"
25+ @keydown.enter.native.prevent =" goToCategory(localePath(getCatLink(category)))"
1526 />
1627 </div >
1728 <HeaderNavigationSubcategories
1829 v-if =" hasChildren(currentCategory)"
1930 :current-category =" currentCategory"
20- @hideSubcategories =" setCurrentCategory(null)"
31+ :has-focus =" hasFocus"
32+ @hideSubcategories =" focusRootElementAndHideSubcategories"
2133 />
2234 </div >
2335</template >
2436<script lang="ts">
2537import {
26- defineComponent , PropType , ref ,
38+ defineComponent , PropType , ref , useRouter ,
2739} from ' @nuxtjs/composition-api' ;
2840import HeaderNavigationItem from ' ./HeaderNavigationItem.vue' ;
2941
@@ -44,19 +56,74 @@ export default defineComponent({
4456 },
4557 setup() {
4658 const { getCatLink } = useUiHelpers ();
59+ const router = useRouter ();
60+
4761 const currentCategory = ref <CategoryTree >(null );
62+ const lvl0CatRefs = ref ([]);
63+ const hasFocus = ref (false );
64+ let lvl0CatFocusIdx = 0 ;
65+ let focusedElement = null ;
4866
4967 const setCurrentCategory = (category : CategoryTree | null ) => {
5068 currentCategory .value = category ;
5169 };
5270
5371 const hasChildren = (category : CategoryTree ) => Boolean (category ?.children );
5472
73+ const setFocus = (event ) => {
74+ focusedElement = event .target ;
75+ lvl0CatFocusIdx = Number (event .target .dataset .index );
76+ hasFocus .value = true ;
77+ };
78+
79+ const focusRootElementAndHideSubcategories = () => {
80+ setCurrentCategory (null );
81+ if (focusedElement !== null ) focusedElement .focus ();
82+ };
83+
84+ const navRight = () => {
85+ lvl0CatFocusIdx ++ ;
86+ if (lvl0CatRefs .value [lvl0CatFocusIdx ]) {
87+ lvl0CatRefs .value [lvl0CatFocusIdx ].$el .focus ();
88+ focusedElement = lvl0CatRefs .value [lvl0CatFocusIdx ].$el ;
89+ } else {
90+ lvl0CatFocusIdx -- ;
91+ }
92+ };
93+
94+ const navLeft = () => {
95+ lvl0CatFocusIdx -- ;
96+ if (lvl0CatRefs .value [lvl0CatFocusIdx ]) {
97+ lvl0CatRefs .value [lvl0CatFocusIdx ].$el .focus ();
98+ focusedElement = lvl0CatRefs .value [lvl0CatFocusIdx ].$el ;
99+ } else {
100+ lvl0CatFocusIdx ++ ;
101+ }
102+ };
103+
104+ const onMouseEnter = (category : CategoryTree ) => {
105+ currentCategory .value = category ;
106+ focusedElement = null ;
107+ hasFocus .value = false ;
108+ };
109+
110+ const goToCategory = (path : string ) => {
111+ router .push (path );
112+ };
113+
55114 return {
56115 getCatLink ,
57116 setCurrentCategory ,
58117 currentCategory ,
59118 hasChildren ,
119+ setFocus ,
120+ focusRootElementAndHideSubcategories ,
121+ lvl0CatRefs ,
122+ navRight ,
123+ navLeft ,
124+ hasFocus ,
125+ onMouseEnter ,
126+ goToCategory ,
60127 };
61128 },
62129});
0 commit comments