Skip to content

Conversation

@Pareder
Copy link
Contributor

@Pareder Pareder commented Dec 24, 2025

Do not pass aria attributes to wrapper div as they are already passes to correct input component (https://github.com/react-component/select/blob/master/src/SelectInput/Content/index.tsx#L17). It improves the overall accessibility.

Closes ant-design/ant-design#46030

Summary by CodeRabbit

发布说明

  • 改进

    • 增强了选择器组件对ARIA属性和角色属性的处理能力,确保这些属性正确传播到内部元素。
  • 测试

    • 新增可访问性测试,验证ARIA和角色属性的正确传播和分配。

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Dec 24, 2025

@Pareder is attempting to deploy a commit to the React Component Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 24, 2025

Walkthrough

该PR调整了Select组件中ARIA属性和role属性的分配方式。扩展BaseSelectProps以支持role属性,修改SelectInput的属性转发逻辑以避免直接在根元素上展开ARIA属性,并从上下文Props中移除role字段。同时添加测试验证ARIA属性正确传播到内部Input元素。

Changes

Cohort / File(s) 变更说明
类型定义和接口更新
src/BaseSelect/index.tsx, src/hooks/useBaseProps.ts
BaseSelectProps扩展以支持role HTML属性;BaseSelectContextProps接口移除可选的role字段
属性转发逻辑调整
src/SelectInput/index.tsx
引入pickAttrs工具函数,分离ARIA属性计算逻辑,确保ARIA props不直接展开到根DOM元素
测试验证
tests/Accessibility.test.tsx, tests/Select.test.tsx
添加新的可访问性测试验证aria和role属性正确传播到Input元素;移除测试中的类型断言

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • zombieJ

Poem

🐰 选择框有新的装扮,
ARIA属性不再乱展,
Input元素接住它们,
role和属性各得其所,
无障碍之路更通畅,
兔子们为代码欢唱! 🌟

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确总结了主要变更:阻止 aria 属性被传递到包装 div,与代码改动(在 SelectInput 中过滤 ARIA 属性)高度相关。
Linked Issues check ✅ Passed PR 实现了 issue #46030 的要求:通过在 SelectInput 中分离 ARIA 属性,确保 aria-required 等属性被传递给输入元素而非包装 div。
Out of Scope Changes check ✅ Passed 所有改动都直接服务于修复目标:BaseSelectProps 扩展 role 属性支持,SelectInput 过滤 ARIA 属性,useBaseProps 移除 role 属性,测试验证新行为。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello @Pareder, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the accessibility of the Select component by refining how ARIA attributes and the role prop are handled. Previously, these attributes were inadvertently applied to the non-interactive wrapper div, leading to potential issues for assistive technologies. The changes now ensure these crucial accessibility properties are correctly passed directly to the underlying input element, improving semantic meaning and user experience for screen reader users.

Highlights

  • Accessibility Improvement: Prevents aria attributes and the role prop from being incorrectly passed to the wrapper div of the Select component.
  • Correct Prop Delegation: Ensures aria attributes and role are now correctly delegated to the interactive input element within the Select component.
  • Issue Resolution: Addresses and closes issue #46030, which reported this accessibility concern.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link

codecov bot commented Dec 24, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.42%. Comparing base (73d9975) to head (820539a).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1190   +/-   ##
=======================================
  Coverage   99.42%   99.42%           
=======================================
  Files          31       31           
  Lines        1216     1218    +2     
  Branches      433      433           
=======================================
+ Hits         1209     1211    +2     
  Misses          7        7           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request aims to improve accessibility by preventing ARIA attributes from being passed to the wrapper div and ensuring they are only applied to the input element. The changes are generally well-implemented, including updates to prop types, context, and the addition of tests to verify the new behavior. However, I've identified a potential issue where the role attribute might not be correctly filtered out from the wrapper div. My review includes a specific suggestion to address this.


// ===================== Render =====================
const domProps = omit(restProps, DEFAULT_OMIT_PROPS as any);
const ariaProps = pickAttrs(domProps, { aria: true });

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The pickAttrs utility with the { aria: true } option doesn't include the role attribute. This means role will not be added to ariaKeys and will not be omitted from the wrapper div, which contradicts the goal of this PR and the associated tests. To ensure role is also filtered out, you should include role: true in the pickAttrs options.

Suggested change
const ariaProps = pickAttrs(domProps, { aria: true });
const ariaProps = pickAttrs(domProps, { aria: true, role: true });

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/SelectInput/index.tsx (1)

220-229: 自定义根组件应该过滤 ARIA 属性以保持一致性

RootComponent 情况下(第 220-228 行),domProps 被完整展开,包含了 ARIA 属性。然而,在主 div 元素上(第 234 行),代码明确使用 omit(domProps, ariaKeys) 来排除 ARIA 属性。

这造成了不一致的行为:自定义根组件会接收 ARIA 属性,而默认 div 不会。根据第 211-212 行提取 ariaKeys 的逻辑,应该在传递给 RootComponent 时也过滤掉 ARIA 属性,或者需要在代码中添加注释说明为什么要对自定义组件特殊处理。

🧹 Nitpick comments (1)
src/SelectInput/index.tsx (1)

211-212: 可选的代码清理建议

ariaProps 变量被计算但未在代码中显式使用。虽然 ARIA 属性通过上下文正确传递到内部组件,但可以考虑添加注释说明为何计算此变量,或者如果不需要可以直接使用 pickAttrs 的返回值提取 keys:

🔎 可选的重构建议
-  const ariaProps = pickAttrs(domProps, { aria: true });
-  const ariaKeys = Object.keys(ariaProps) as (keyof typeof domProps)[];
+  // Extract ARIA attribute keys to omit from root element
+  const ariaKeys = Object.keys(pickAttrs(domProps, { aria: true })) as (keyof typeof domProps)[];
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 73d9975 and 820539a.

⛔ Files ignored due to path filters (1)
  • tests/__snapshots__/Select.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (5)
  • src/BaseSelect/index.tsx
  • src/SelectInput/index.tsx
  • src/hooks/useBaseProps.ts
  • tests/Accessibility.test.tsx
  • tests/Select.test.tsx
💤 Files with no reviewable changes (1)
  • src/hooks/useBaseProps.ts
🔇 Additional comments (3)
src/SelectInput/index.tsx (1)

14-14: LGTM!

正确引入了 pickAttrs 工具函数用于提取 ARIA 属性。

tests/Select.test.tsx (1)

139-146: LGTM!

移除了 as any 类型断言是一个好的改进,说明类型系统现在正确支持 role 属性。这与 BaseSelectProps 扩展 Pick<React.HTMLAttributes<HTMLElement>, 'role'> 的更改保持一致。

src/BaseSelect/index.tsx (1)

132-136: LGTM!

通过扩展 Pick<React.HTMLAttributes<HTMLElement>, 'role'> 正确地将 role 属性添加到公共 API。这使得组件可以通过标准 HTML 属性接收 role,与 ARIA 属性处理保持一致。

Comment on lines +217 to +243
it('should pass aria and role attributes to Input component', async () => {
const { container } = render(
<Select
role="group"
aria-required="true"
options={[
{
value: '123',
},
{
value: '1234',
},
{
value: '12345',
},
]}
/>,
);

const wrapper = container.querySelector('.rc-select');
expect(wrapper).not.toHaveAttribute('role');
expect(wrapper).not.toHaveAttribute('aria-required');

const input = container.querySelector('input');
expect(input).toHaveAttribute('role', 'group');
expect(input).toHaveAttribute('aria-required', 'true');
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

WAI-ARIA Select component appropriate role combobox listbox

💡 Result:

Short answer

  • Use role="combobox" on the control when you have a single control that opens a popup for choosing a value (editable or select‑only). The popup element should use role="listbox" (or tree/grid/dialog if appropriate) and each item uses role="option". Manage aria-expanded, aria-controls, aria-activedescendant, and aria-autocomplete as required. [1][2]

When to use listbox without combobox

  • If the UI is simply a persistent list of options (not a single control that opens/closes a popup), use role="listbox" for the list and role="option" for items — no combobox required. [3]

Key ARIA requirements (summary)

  • combobox element: role="combobox", aria-expanded (true/false), aria-controls → id of popup, aria-haspopup defaults to "listbox". [1][2]
  • popup: role="listbox" and children role="option"; when focus remains on the combobox use aria-activedescendant to indicate the highlighted option. [1][2]
  • If editable/autocomplete, set aria-autocomplete on the combobox/textbox. [1]

References

  • WAI-ARIA 1.2 (combobox role & structural rules). [1]
  • WAI-ARIA Authoring Practices — Combobox pattern & examples. [2]
  • MDN — listbox role guidance. [3]

🏁 Script executed:

# Find and examine the Select component implementation around line 265
find . -type f -name "*.tsx" -o -name "*.ts" | head -20

Repository: react-component/select

Length of output: 716


🏁 Script executed:

# Search for the Select component implementation to understand default role
rg -t tsx -t ts "role.*combobox|role.*group" --context 3

Repository: react-component/select

Length of output: 93


🏁 Script executed:

# Look for the test file to understand the full context
find . -path "*/tests/*Accessibility*" -type f

Repository: react-component/select

Length of output: 96


🏁 Script executed:

# Examine the Accessibility test file around line 265
cat -n ./tests/Accessibility.test.tsx | sed -n '260,280p'

Repository: react-component/select

Length of output: 936


🏁 Script executed:

# Search for Select component implementation and default role
rg "role.*=.*combobox|role.*=.*group" --context 2

Repository: react-component/select

Length of output: 3100


🏁 Script executed:

# Look for the main Select component file
find . -type f -name "*.tsx" -o -name "*.ts" | grep -i select | head -10

Repository: react-component/select

Length of output: 392


🏁 Script executed:

# Search for role attribute assignments in the codebase
rg "role\s*=" --context 2 | head -50

Repository: react-component/select

Length of output: 2732


测试验证了属性传播机制,但使用的 ARIA role 不符合无障碍标准

新测试用例正确验证了属性在 Select 组件中的传播行为:包装器 div 不接收 rolearia-required,而内部 input 元素接收这些属性。

但根据 WAI-ARIA 规范,Select 组件的 input 元素应使用 role="combobox",而非 role="group"role="group" 通常用于分组相关元素,并不适合 Select 组件(见 line 265 的默认实现)。建议使用 role="combobox" 重写该测试,以遵循无障碍最佳实践。

🤖 Prompt for AI Agents
In tests/Accessibility.test.tsx around lines 217 to 243, the test uses
role="group" which is incorrect for a Select input; update the test to pass
role="combobox" into the Select props and change the assertions to expect the
internal input to have role "combobox" (while still asserting the wrapper does
not have role or aria-required), so the test aligns with the component's default
ARIA role and accessibility expectations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Select has aria-required on the wrong element

1 participant