@@ -11,16 +11,12 @@ import { MenuOpenContext, MenubarContext } from './contexts';
11
11
import usePrevious from '../../common/usePrevious' ;
12
12
13
13
/**
14
- * @component
15
- * @param {object } props
14
+ * Menubar manages a collection of menu items and their submenus. It provides keyboard navigation,
15
+ * focus and state management, and other accessibility features for the menu items and submenus.
16
+ *
16
17
* @param {React.ReactNode } props.children - Menu items that will be rendered in the menubar
17
18
* @param {string } [props.className='nav__menubar'] - CSS class name to apply to the menubar
18
19
* @returns {JSX.Element }
19
- */
20
-
21
- /**
22
- * Menubar manages a collection of menu items and their submenus. It provides keyboard navigation,
23
- * focus and state management, and other accessibility features for the menu items and submenus.
24
20
*
25
21
* @example
26
22
* <Menubar>
@@ -31,20 +27,16 @@ import usePrevious from '../../common/usePrevious';
31
27
*/
32
28
33
29
function Menubar ( { children, className } ) {
34
- // core state for menu management
35
30
const [ menuOpen , setMenuOpen ] = useState ( 'none' ) ;
36
31
const [ activeIndex , setActiveIndex ] = useState ( 0 ) ;
37
32
const prevIndex = usePrevious ( activeIndex ) ;
38
33
const [ hasFocus , setHasFocus ] = useState ( false ) ;
39
34
40
- // refs for menu items and their ids
41
35
const menuItems = useRef ( new Set ( ) ) . current ;
42
36
const menuItemToId = useRef ( new Map ( ) ) . current ;
43
37
44
- // ref for hiding submenus
45
38
const timerRef = useRef ( null ) ;
46
39
47
- // get the id of a menu item by its index
48
40
const getMenuId = useCallback (
49
41
( index ) => {
50
42
const items = Array . from ( menuItems ) ;
@@ -54,9 +46,6 @@ function Menubar({ children, className }) {
54
46
[ menuItems , menuItemToId , activeIndex ]
55
47
) ;
56
48
57
- /**
58
- * navigation functions
59
- */
60
49
const prev = useCallback ( ( ) => {
61
50
const newIndex = ( activeIndex - 1 + menuItems . size ) % menuItems . size ;
62
51
setActiveIndex ( newIndex ) ;
@@ -85,8 +74,6 @@ function Menubar({ children, className }) {
85
74
setActiveIndex ( menuItems . size - 1 ) ;
86
75
} , [ ] ) ;
87
76
88
- // closes the menu and returns focus to the active menu item
89
- // is called on Escape key press
90
77
const close = useCallback ( ( ) => {
91
78
if ( menuOpen === 'none' ) return ;
92
79
@@ -96,27 +83,17 @@ function Menubar({ children, className }) {
96
83
activeNode . focus ( ) ;
97
84
} , [ activeIndex , menuItems , menuOpen ] ) ;
98
85
99
- // toggle the open state of a submenu
100
86
const toggleMenuOpen = useCallback ( ( id ) => {
101
87
setMenuOpen ( ( prevState ) => ( prevState === id ? 'none' : id ) ) ;
102
88
} ) ;
103
89
104
- /**
105
- * Register top level menu items. Stores both the DOM node and the id of the submenu.
106
- * Access to the DOM node is needed for focus management and tabindex control,
107
- * while the id is needed to toggle the submenu open and closed.
108
- *
109
- * @param {React.RefObject } ref - a ref to the DOM node of the menu item
110
- * @param {string } submenuId - the id of the submenu that the menu item opens
111
- *
112
- */
113
90
const registerTopLevelItem = useCallback (
114
91
( ref , submenuId ) => {
115
92
const menuItemNode = ref . current ;
116
93
117
94
if ( menuItemNode ) {
118
95
menuItems . add ( menuItemNode ) ;
119
- menuItemToId . set ( menuItemNode , submenuId ) ; // store the id of the submenu
96
+ menuItemToId . set ( menuItemNode , submenuId ) ;
120
97
}
121
98
122
99
return ( ) => {
@@ -127,9 +104,6 @@ function Menubar({ children, className }) {
127
104
[ menuItems , menuItemToId ]
128
105
) ;
129
106
130
- /**
131
- * focus and blur management
132
- */
133
107
const clearHideTimeout = useCallback ( ( ) => {
134
108
if ( timerRef . current ) {
135
109
clearTimeout ( timerRef . current ) ;
@@ -164,7 +138,6 @@ function Menubar({ children, className }) {
164
138
[ nodeRef ]
165
139
) ;
166
140
167
- // keyboard navigation
168
141
const keyHandlers = {
169
142
ArrowLeft : ( e ) => {
170
143
e . preventDefault ( ) ;
@@ -183,7 +156,6 @@ function Menubar({ children, className }) {
183
156
} ,
184
157
Tab : ( e ) => {
185
158
e . stopPropagation ( ) ;
186
- // close
187
159
} ,
188
160
Home : ( e ) => {
189
161
e . preventDefault ( ) ;
@@ -195,17 +167,15 @@ function Menubar({ children, className }) {
195
167
e . stopPropagation ( ) ;
196
168
last ( ) ;
197
169
}
198
- // to do : support direct access keys
170
+ // TO DO : support direct access keys
199
171
} ;
200
172
201
- // focus the active menu item and set its tabindex
202
173
useEffect ( ( ) => {
203
174
if ( activeIndex !== prevIndex ) {
204
175
const items = Array . from ( menuItems ) ;
205
176
const activeNode = items [ activeIndex ] ;
206
177
const prevNode = items [ prevIndex ] ;
207
178
208
- // roving tabindex
209
179
prevNode ?. setAttribute ( 'tabindex' , '-1' ) ;
210
180
activeNode ?. setAttribute ( 'tabindex' , '0' ) ;
211
181
@@ -219,7 +189,6 @@ function Menubar({ children, className }) {
219
189
clearHideTimeout ( ) ;
220
190
} , [ clearHideTimeout ] ) ;
221
191
222
- // context value for dropdowns and menu items
223
192
const contextValue = useMemo (
224
193
( ) => ( {
225
194
createMenuHandlers : ( menu ) => ( {
0 commit comments