From 74e8bd9ba1cdd2ac243d8bbbe03155c5da2edca2 Mon Sep 17 00:00:00 2001 From: Usman Khurshid Date: Wed, 8 Jul 2026 23:14:44 +0500 Subject: [PATCH 1/2] fix: allow browser back/forward navigation in Tabs (Cmd+Left/Right on Mac, Alt+Left/Right on Windows) When users press Cmd+Left/Right (Mac) or Alt+Left/Right (Windows/Linux) to navigate browser history, the Tabs component was capturing these keystrokes and switching tabs instead of letting the browser handle back/forward navigation. Added keyboard shortcut handlers in useTabList that explicitly allow propagation for these browser navigation key combinations, while preserving normal tab navigation with unmodified arrow keys. Fixes #9648 --- .../react-aria-components/test/Tabs.test.js | 30 +++++++++++++++++++ packages/react-aria/src/tabs/useTabList.ts | 16 +++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/packages/react-aria-components/test/Tabs.test.js b/packages/react-aria-components/test/Tabs.test.js index d5d34e78e07..0f88b9ed524 100644 --- a/packages/react-aria-components/test/Tabs.test.js +++ b/packages/react-aria-components/test/Tabs.test.js @@ -1079,4 +1079,34 @@ describe('Tabs', () => { expect(menu.getOptions()).toHaveLength(3); await menu.close(); }); + + it('allows browser back/forward navigation (Meta+ArrowLeft/Right on Mac, Alt+ArrowLeft/Right on Windows)', async () => { + let {getByRole} = renderTabs(); + let tabsTester = testUtilUser.createTester('Tabs', {root: getByRole('tablist')}); + let tabs = tabsTester.getTabs(); + + // Select first tab + await tabsTester.triggerTab({tab: 0}); + expect(tabsTester.getSelectedTab()).toBe(tabs[0]); + + // Try to navigate with Meta+ArrowRight (Mac browser back/forward) - should NOT switch tabs + await user.keyboard('{Meta>}{ArrowRight}{/Meta}'); + expect(tabsTester.getSelectedTab()).toBe(tabs[0]); + + // Try to navigate with Meta+ArrowLeft - should NOT switch tabs + await user.keyboard('{Meta>}{ArrowLeft}{/Meta}'); + expect(tabsTester.getSelectedTab()).toBe(tabs[0]); + + // Try to navigate with Alt+ArrowRight (Windows browser back/forward) - should NOT switch tabs + await user.keyboard('{Alt>}{ArrowRight}{/Alt}'); + expect(tabsTester.getSelectedTab()).toBe(tabs[0]); + + // Try to navigate with Alt+ArrowLeft - should NOT switch tabs + await user.keyboard('{Alt>}{ArrowLeft}{/Alt}'); + expect(tabsTester.getSelectedTab()).toBe(tabs[0]); + + // Regular arrow keys should still work + await user.keyboard('{ArrowRight}'); + expect(tabsTester.getSelectedTab()).toBe(tabs[1]); + }); }); diff --git a/packages/react-aria/src/tabs/useTabList.ts b/packages/react-aria/src/tabs/useTabList.ts index d960df03d4d..01825f1579f 100644 --- a/packages/react-aria/src/tabs/useTabList.ts +++ b/packages/react-aria/src/tabs/useTabList.ts @@ -26,6 +26,7 @@ import {useLabels} from '../utils/useLabels'; import {useLocale} from '../i18n/I18nProvider'; import {useMemo} from 'react'; import {useSelectableCollection} from '../selection/useSelectableCollection'; +import {useKeyboard} from '../interactions/useKeyboard'; export interface AriaTabListProps extends TabListProps, DOMProps, AriaLabelingProps { /** @@ -76,6 +77,19 @@ export function useTabList( linkBehavior: 'selection' }); + // Add keyboard handlers to allow browser back/forward navigation (Cmd+Left/Right on Mac, Alt+Left/Right on Windows) + // to propagate so the browser can handle them instead of switching tabs. + let {keyboardProps} = useKeyboard({ + shortcuts: { + // On Mac, Cmd+Left/Right are browser back/forward + 'Meta+ArrowLeft': () => ({shouldContinuePropagation: true}), + 'Meta+ArrowRight': () => ({shouldContinuePropagation: true}), + // On Windows/Linux, Alt+Left/Right are browser back/forward + 'Alt+ArrowLeft': () => ({shouldContinuePropagation: true}), + 'Alt+ArrowRight': () => ({shouldContinuePropagation: true}) + } + }); + // Compute base id for all tabs let tabsId = useId(); tabsIds.set(state, tabsId); @@ -84,7 +98,7 @@ export function useTabList( return { tabListProps: { - ...mergeProps(collectionProps, tabListLabelProps), + ...mergeProps(collectionProps, tabListLabelProps, keyboardProps), role: 'tablist', 'aria-orientation': orientation, tabIndex: undefined From 91a9b14e297227be8140b25cee35790474fbe126 Mon Sep 17 00:00:00 2001 From: Usman Khurshid Date: Thu, 9 Jul 2026 01:04:01 +0500 Subject: [PATCH 2/2] fix: correct import order for lint compliance --- packages/react-aria/src/tabs/useTabList.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-aria/src/tabs/useTabList.ts b/packages/react-aria/src/tabs/useTabList.ts index 01825f1579f..640591c45e9 100644 --- a/packages/react-aria/src/tabs/useTabList.ts +++ b/packages/react-aria/src/tabs/useTabList.ts @@ -25,8 +25,8 @@ import {useId} from '../utils/useId'; import {useLabels} from '../utils/useLabels'; import {useLocale} from '../i18n/I18nProvider'; import {useMemo} from 'react'; -import {useSelectableCollection} from '../selection/useSelectableCollection'; import {useKeyboard} from '../interactions/useKeyboard'; +import {useSelectableCollection} from '../selection/useSelectableCollection'; export interface AriaTabListProps extends TabListProps, DOMProps, AriaLabelingProps { /**