@@ -67,7 +67,7 @@ const Menu = React.forwardRef(function Menu(
67
67
68
68
const [ position , setPosition ] = useState ( [ - 1 , - 1 ] ) ;
69
69
const focusableItems = childContext . state . items . filter (
70
- ( item ) => ! item . disabled
70
+ ( item ) => ! item . disabled && item . ref . current
71
71
) ;
72
72
73
73
function returnFocus ( ) {
@@ -80,7 +80,6 @@ const Menu = React.forwardRef(function Menu(
80
80
if ( menu . current ) {
81
81
focusReturn . current = document . activeElement ;
82
82
setPosition ( calculatePosition ( ) ) ;
83
- menu . current . focus ( ) ;
84
83
}
85
84
}
86
85
@@ -101,11 +100,6 @@ const Menu = React.forwardRef(function Menu(
101
100
function handleKeyDown ( e ) {
102
101
e . stopPropagation ( ) ;
103
102
104
- const currentItem = focusableItems . findIndex ( ( item ) =>
105
- item . ref . current . contains ( document . activeElement )
106
- ) ;
107
- let indexToFocus = currentItem ;
108
-
109
103
// if the user presses escape or this is a submenu
110
104
// and the user presses ArrowLeft, close it
111
105
if (
@@ -114,28 +108,39 @@ const Menu = React.forwardRef(function Menu(
114
108
) {
115
109
handleClose ( e ) ;
116
110
} else {
117
- // if currentItem is -1, the menu itself is focused.
118
- // in this case, the arrow keys define the first item
119
- // to be focused.
111
+ focusItem ( e ) ;
112
+ }
113
+ }
114
+
115
+ function focusItem ( e ) {
116
+ const currentItem = focusableItems . findIndex ( ( item ) =>
117
+ item . ref . current . contains ( document . activeElement )
118
+ ) ;
119
+ let indexToFocus = currentItem ;
120
+
121
+ // if currentItem is -1, no menu item is focused yet.
122
+ // in this case, the first item should receive focus.
123
+ if ( currentItem === - 1 ) {
124
+ indexToFocus = 0 ;
125
+ } else if ( e ) {
120
126
if ( match ( e , keys . ArrowUp ) ) {
121
- indexToFocus =
122
- currentItem === - 1 ? focusableItems . length - 1 : indexToFocus - 1 ;
127
+ indexToFocus = indexToFocus - 1 ;
123
128
}
124
129
if ( match ( e , keys . ArrowDown ) ) {
125
- indexToFocus = currentItem === - 1 ? 0 : indexToFocus + 1 ;
130
+ indexToFocus = indexToFocus + 1 ;
126
131
}
132
+ }
127
133
128
- if ( indexToFocus < 0 ) {
129
- indexToFocus = 0 ;
130
- }
131
- if ( indexToFocus >= focusableItems . length ) {
132
- indexToFocus = focusableItems . length - 1 ;
133
- }
134
+ if ( indexToFocus < 0 ) {
135
+ indexToFocus = focusableItems . length - 1 ;
136
+ }
137
+ if ( indexToFocus >= focusableItems . length ) {
138
+ indexToFocus = 0 ;
139
+ }
134
140
135
- if ( indexToFocus !== currentItem ) {
136
- const nodeToFocus = focusableItems [ indexToFocus ] ;
137
- nodeToFocus . ref . current . focus ( ) ;
138
- }
141
+ if ( indexToFocus !== currentItem ) {
142
+ const nodeToFocus = focusableItems [ indexToFocus ] ;
143
+ nodeToFocus . ref . current . focus ( ) ;
139
144
}
140
145
}
141
146
@@ -198,6 +203,13 @@ const Menu = React.forwardRef(function Menu(
198
203
return [ - 1 , - 1 ] ;
199
204
}
200
205
206
+ useEffect ( ( ) => {
207
+ if ( open && focusableItems . length > 0 ) {
208
+ focusItem ( ) ;
209
+ }
210
+ // eslint-disable-next-line react-hooks/exhaustive-deps
211
+ } , [ open , focusableItems ] ) ;
212
+
201
213
useEffect ( ( ) => {
202
214
if ( open ) {
203
215
handleOpen ( ) ;
0 commit comments