@@ -19,6 +19,7 @@ import {
19
19
} from '../internal/context/single-tab-stop-navigation-context' ;
20
20
import { hasModifierKeys , isPlainLeftClick } from '../internal/events' ;
21
21
import useHiddenDescription from '../internal/hooks/use-hidden-description' ;
22
+ import { usePrevious } from '../internal/hooks/use-previous' ;
22
23
import { useVisualRefresh } from '../internal/hooks/use-visual-mode' ;
23
24
import { KeyCode } from '../internal/keycode' ;
24
25
import { circleIndex } from '../internal/utils/circle-index' ;
@@ -112,6 +113,7 @@ export function TabHeaderBar({
112
113
const [ focusedTabId , setFocusedTabId ] = useState ( activeTabId ) ;
113
114
const [ previousActiveTabId , setPreviousActiveTabId ] = useState < string | undefined > ( activeTabId ) ;
114
115
const hasActionOrDismissible = tabs . some ( tab => tab . action || tab . dismissible ) ;
116
+ const hadActionOrDismissible = usePrevious ( hasActionOrDismissible ) ;
115
117
const tabActionAttributes = hasActionOrDismissible
116
118
? {
117
119
role : 'application' ,
@@ -124,6 +126,16 @@ export function TabHeaderBar({
124
126
role : 'tablist' ,
125
127
} ;
126
128
129
+ useEffect ( ( ) => {
130
+ if ( hadActionOrDismissible && ! hasActionOrDismissible ) {
131
+ // when tabs becomes non-dismissible (e.g. when all dismissible tabs are removed),
132
+ // the hasActionOrDismissible is changing which causing tabs to re-mount to the React tree,
133
+ // which, in turn, causes losing their refs, and the nextActive.focus() function inside handleDismiss does not focus on the next tab
134
+ // so this code does
135
+ getNextFocusTarget ( ) ?. focus ( ) ;
136
+ }
137
+ } , [ hasActionOrDismissible , hadActionOrDismissible ] ) ;
138
+
127
139
useEffect ( ( ) => {
128
140
if ( headerBarRef . current ) {
129
141
setHorizontalOverflow ( hasHorizontalOverflow ( headerBarRef . current , inlineStartOverflowButton ) ) ;
0 commit comments