diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 63ec961b80f3c..48827c815c585 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -15,6 +15,10 @@ - `ProgressBar`: Fix CSS variable with invalid value ([#60576](https://github.com/WordPress/gutenberg/pull/60576)). +### Experimental + +- `Tabs`: Fallback to first enabled tab if no active tab id ([#60681](https://github.com/WordPress/gutenberg/pull/60681)). + ## 27.3.0 (2024-04-03) ### Bug Fix diff --git a/packages/components/src/tabs/index.tsx b/packages/components/src/tabs/index.tsx index 5ffa8e97a651b..aaae3ed252750 100644 --- a/packages/components/src/tabs/index.tsx +++ b/packages/components/src/tabs/index.tsx @@ -153,6 +153,14 @@ function Tabs( { } }, [ isControlled, selectedTab, selectedTabId, setSelectedId ] ); + useEffect( () => { + // If there is no active tab, fallback to place focus on the first enabled tab + // so there is always an active element + if ( selectedTabId === null && ! activeId && firstEnabledTab?.id ) { + setActiveId( firstEnabledTab.id ); + } + }, [ selectedTabId, activeId, firstEnabledTab?.id, setActiveId ] ); + useEffect( () => { if ( ! isControlled ) { return; diff --git a/packages/components/src/tabs/test/index.tsx b/packages/components/src/tabs/test/index.tsx index 39c860de62c14..bbb7f591d0ffc 100644 --- a/packages/components/src/tabs/test/index.tsx +++ b/packages/components/src/tabs/test/index.tsx @@ -242,6 +242,44 @@ describe( 'Tabs', () => { await press.Tab(); expect( alphaButton ).toHaveFocus(); } ); + + it( 'should focus on the first enabled tab when pressing the Tab key if no tab is selected', async () => { + const TABS_WITH_ALPHA_DISABLED = TABS.map( ( tabObj ) => + tabObj.tabId === 'alpha' + ? { + ...tabObj, + tab: { + ...tabObj.tab, + disabled: true, + }, + } + : tabObj + ); + + render( + + ); + + await sleep(); + await press.Tab(); + expect( + await screen.findByRole( 'tab', { name: 'Beta' } ) + ).toHaveFocus(); + + await press.ArrowRight(); + expect( + await screen.findByRole( 'tab', { name: 'Gamma' } ) + ).toHaveFocus(); + + await press.Tab(); + await press.ShiftTab(); + expect( + await screen.findByRole( 'tab', { name: 'Gamma' } ) + ).toHaveFocus(); + } ); } ); describe( 'Tab Attributes', () => {