From e083234cbf73b57f5c37d4d81162c420048a133b Mon Sep 17 00:00:00 2001 From: rubenmarcus Date: Thu, 24 Sep 2026 14:02:59 +0100 Subject: [PATCH 1/2] fix: scope tablist role to nav list to exclude extra content --- src/TabNavList/index.tsx | 4 ++-- tests/__snapshots__/index.test.tsx.snap | 8 ++++---- tests/accessibility.test.tsx | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/TabNavList/index.tsx b/src/TabNavList/index.tsx index 4e64f242..fd519dc9 100644 --- a/src/TabNavList/index.tsx +++ b/src/TabNavList/index.tsx @@ -611,8 +611,6 @@ const TabNavList = React.forwardRef((props, ref
{ @@ -635,6 +633,8 @@ const TabNavList = React.forwardRef((props, ref
{ expect(queryByRole('tab', { name: /Tab1/i })).toBeInTheDocument(); expect(queryByRole('tab', { name: /Tab3/i })).toBeInTheDocument(); }); + + it('should scope tablist role to the nav list so extra content is not owned by the tablist', () => { + const { container, getByRole } = render( + createTabs({ + tabBarExtraContent: { + left: , + right: , + }, + }), + ); + + const navList = getByRole('tablist'); + expect(navList).toHaveClass('rc-tabs-nav-list'); + expect(container.querySelector('.rc-tabs-nav')).not.toHaveAttribute('role'); + + // Extra content and operations buttons live outside the tablist element, + // so the tablist only owns tab nodes (axe: aria-required-children). + expect(navList.querySelector('button')).toBeNull(); + }); }); From 02beb8390769216a266b0f0899054efdd53b4fd0 Mon Sep 17 00:00:00 2001 From: rubenmarcus Date: Sat, 26 Sep 2026 03:14:34 +0100 Subject: [PATCH 2/2] test: assert extra content buttons render before tablist scope check --- tests/accessibility.test.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/accessibility.test.tsx b/tests/accessibility.test.tsx index 7b6d91c2..0d160534 100644 --- a/tests/accessibility.test.tsx +++ b/tests/accessibility.test.tsx @@ -357,6 +357,10 @@ describe('Tabs.Accessibility', () => { // Extra content and operations buttons live outside the tablist element, // so the tablist only owns tab nodes (axe: aria-required-children). + // Confirm both extra buttons rendered first, so the querySelector below + // cannot pass vacuously when extra content fails to mount. + getByRole('button', { name: 'Left Extra' }); + getByRole('button', { name: 'Right Extra' }); expect(navList.querySelector('button')).toBeNull(); }); });