@@ -19,6 +19,7 @@ import {
1919} from '../internal/context/single-tab-stop-navigation-context' ;
2020import { hasModifierKeys , isPlainLeftClick } from '../internal/events' ;
2121import useHiddenDescription from '../internal/hooks/use-hidden-description' ;
22+ import { usePrevious } from '../internal/hooks/use-previous' ;
2223import { useVisualRefresh } from '../internal/hooks/use-visual-mode' ;
2324import { KeyCode } from '../internal/keycode' ;
2425import { circleIndex } from '../internal/utils/circle-index' ;
@@ -112,6 +113,7 @@ export function TabHeaderBar({
112113 const [ focusedTabId , setFocusedTabId ] = useState ( activeTabId ) ;
113114 const [ previousActiveTabId , setPreviousActiveTabId ] = useState < string | undefined > ( activeTabId ) ;
114115 const hasActionOrDismissible = tabs . some ( tab => tab . action || tab . dismissible ) ;
116+ const hadActionOrDismissible = usePrevious ( hasActionOrDismissible ) ;
115117 const tabActionAttributes = hasActionOrDismissible
116118 ? {
117119 role : 'application' ,
@@ -124,6 +126,16 @@ export function TabHeaderBar({
124126 role : 'tablist' ,
125127 } ;
126128
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+
127139 useEffect ( ( ) => {
128140 if ( headerBarRef . current ) {
129141 setHorizontalOverflow ( hasHorizontalOverflow ( headerBarRef . current , inlineStartOverflowButton ) ) ;
0 commit comments