react-component / react-component/tabs

[Accessibility] tabBarExtraContent is owned by role="tablist"

Open
#1,013 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
572
Forks
241
Avg merge
4d 18h
Merged PRs (30d)
4

Description

Summary

tabBarExtraContent is rendered inside the element with role="tablist". When the extra content is interactive, the tablist therefore owns a non-tab control and axe reports a critical aria-required-children violation.

This is the canonical implementation behind these accepted Ant Design reports:

Minimal reproduction

<Tabs
  items={[{ key: 'one', label: 'One', children: 'Panel one' }]}
  tabBarExtraContent={<button type="button">Extra action</button>}
/>

Run axe with the aria-required-children rule enabled.

A focused probe through current Ant Design master, which uses @rc-component/tabs 1.12.0, produced this reduced structure:

<div role="tablist" aria-orientation="horizontal" class="ant-tabs-nav">
  <div class="ant-tabs-nav-wrap">
    <div class="ant-tabs-nav-list">
      <div role="tab">One</div>
    </div>
  </div>
  <div class="ant-tabs-extra-content">
    <button type="button">Extra action</button>
  </div>
</div>

Observed axe result:

aria-required-children (critical)
Element has children which are not allowed: button
Target: .ant-tabs-nav
Related node: .ant-tabs-extra-content > button

The canonical source has the same structure on current master (bf6dbda):

  • TabNavList/index.tsx puts both ExtraContent positions, the tab nodes, the add control, and OperationNode under the element with role="tablist".
  • ExtraContent.tsx renders the caller-provided content inside that tree.

Expected behavior

The tablist should own the role="tab" elements, while arbitrary interactive extra content remains visually adjacent but outside the tablist's accessibility ownership.

Possible implementation and regression boundaries

One possible direction is to put role="tablist" on an inner element that owns only the tabs, while leaving extra content and other non-tab controls outside it. The exact DOM change needs to preserve the existing tabListRef measurements, scrolling, overflow dropdown, ink bar, and layout behavior.

Regression coverage should include:

  • interactive extra content at both left and right positions;
  • editable add/remove controls and the overflow/more operation;
  • horizontal, vertical, and RTL layouts;
  • existing keyboard navigation and tab measurement/overflow tests;
  • an axe assertion with aria-required-children enabled.

I searched the canonical repository's open and closed issues and PRs and found no duplicate for extra content under the tablist. #809 is related accessibility work, but it concerns the remove button's own role rather than tabBarExtraContent ownership.

AI assistance disclosure: Codex was used to trace canonical ownership, search existing issues and PRs, and run the focused axe reproduction. The reported DOM and axe output were verified against current source.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/TabNavList/index.tsx, especially the tablist wrapper and its placement of ExtraContent, operation controls, and tab nodes; then read src/TabNavList/ExtraContent.tsx. Run the focused axe reproduction with aria-required-children enabled and inspect existing keyboard, measurement, overflow, layout, and RTL tests. Done means extra interactive content is outside tablist ownership without breaking refs, scrolling, overflow, ink-bar behavior, or keyboard navigation.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
accessibility, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.