Skip to content

fix: avoid selecting disabled options via keyboard in Mentions#308

Merged
zombieJ merged 3 commits intoreact-component:masterfrom
QDyanbing:fix/disabled-options
Mar 12, 2026
Merged

fix: avoid selecting disabled options via keyboard in Mentions#308
zombieJ merged 3 commits intoreact-component:masterfrom
QDyanbing:fix/disabled-options

Conversation

@QDyanbing
Copy link
Contributor

@QDyanbing QDyanbing commented Mar 12, 2026

问题

  • 如果候选列表第一项是 disabled,按 Enter 仍会选中它并插入到文本中;
  • 上下方向键会把高亮停在 disabled 选项上,导致 “高亮在灰项 + Enter 插入/无响应” 的不一致体验;
  • 行为与 rc-select 的键盘导航不一致。

修复方案

  • src/Mentions.tsx 中新增 getEnabledActiveIndex,用于从当前索引出发按方向查找下一个非 disabled 的选项。
  • 开始测量和 options 变化时,使用该方法把 activeIndex 校正为首个可用项(全部 disabled 时为 -1)。
  • 上下键时通过 getEnabledActiveIndex 跳过所有 disabled 选项。
  • Enter 时,如果当前高亮项无效或为 disabled,尝试 fallback 到第一个可用项;若全部 disabled,仅结束测量,不修改文本。
  • selectOption 中对 disabled 做早返回,避免任何路径下选中禁用项。
  • DropdownMenu 中,鼠标 hover disabled 项时不再改变 activeIndex,与 rc-select 行为一致。

测试

  • 补充用例覆盖:
    • 第一项为 disabled 时,Enter 应选中下一个可用项;
    • 所有选项 disabled 时,Enter 不修改文本;
    • 上下键导航会跳过中间的 disabled 选项。
  • 本地 npm test 通过。

fix: ant-design/ant-design#56934

Summary by CodeRabbit

  • Bug Fixes

    • 修复禁用选项交互:悬停不会激活禁用项,键盘上下导航会跳过禁用项,开始输入/测量时会重置为首个可用项,回车在当前无有效选项或全部禁用时不会修改输入。
  • Tests

    • 新增覆盖禁用选项的测试(悬停、导航、回车、选项变化与空列表),确保交互稳定且无异常。

@gemini-code-assist
Copy link

Summary of Changes

Hello, 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 improves the user experience and accessibility of the Mentions component by addressing several issues related to disabled options. Previously, users could inadvertently select or highlight disabled options via keyboard navigation, leading to inconsistent and unexpected behavior. The changes introduce robust logic to ensure that all keyboard and mouse interactions correctly respect the disabled state of options, making the component more predictable and user-friendly, and aligning its behavior with common UI patterns.

Highlights

  • Keyboard Navigation for Disabled Options: Implemented a new utility function, getEnabledActiveIndex, to correctly identify and navigate to non-disabled options within the Mentions component's dropdown list.
  • Consistent Active Index Management: Ensured that the activeIndex is always set to an enabled option when the measurement starts, options change, or when navigating with arrow keys, preventing disabled options from being highlighted.
  • Enhanced Enter Key Behavior: Modified the Enter key functionality to intelligently select the first available enabled option if the currently highlighted option is disabled or invalid, or to stop measurement without text modification if all options are disabled.
  • Preventing Selection of Disabled Options: Added an explicit check in the selectOption function to prevent any disabled option from being selected, regardless of the interaction path.
  • Improved Mouse Hover Interaction: Updated the DropdownMenu component to prevent the activeIndex from changing when a user hovers over a disabled option, aligning with standard UI behavior.
  • Comprehensive Test Coverage: Added new test cases to validate the correct behavior of keyboard navigation (Enter, Up/Down arrows) and selection when dealing with disabled options, including scenarios where the first option is disabled, or all options are disabled.

🧠 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.

Changelog
  • src/DropdownMenu.tsx
    • Modified onMouseEnter handler to prevent activeIndex from being set when hovering over a disabled option.
  • src/Mentions.tsx
    • Added getEnabledActiveIndex utility function to find the next non-disabled option.
    • Introduced a useEffect hook to correct the activeIndex to an enabled option when measuring starts or options change.
    • Updated startMeasure to initialize activeIndex using getEnabledActiveIndex(0).
    • Added an early return in selectOption if the selected option is disabled.
    • Refactored onKeyDown for UP and DOWN arrow keys to skip disabled options using getEnabledActiveIndex.
    • Enhanced onKeyDown for the ENTER key to handle disabled options, falling back to the first enabled option or stopping measurement if no enabled options exist.
  • tests/Mentions.spec.tsx
    • Added a test case to verify that the Enter key skips disabled options and selects the next available one.
    • Included a test case to confirm that text remains unchanged when the Enter key is pressed and all options are disabled.
    • Added a test case to ensure that arrow keys correctly skip over disabled options during navigation.
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.

@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8f18fda8-ff3c-4345-8d2b-ad0c1c439808

📥 Commits

Reviewing files that changed from the base of the PR and between 81c0a9f and 4b547cd.

📒 Files selected for processing (1)
  • tests/Mentions.spec.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/Mentions.spec.tsx

Walkthrough

该变更在 DropdownMenu 与 Mentions 中引入对禁用选项的护卫与跳过逻辑,确保在鼠标悬停、键盘导航和回车选择时不会激活或选择被禁用的项,并为 Mentions 添加相关测试覆盖。

Changes

Cohort / File(s) Summary
菜单项鼠标交互
src/DropdownMenu.tsx
在 MenuItem 的 onMouseEnter 中添加守卫,仅当项未禁用时才调用 setActiveIndex(index),防止悬停激活禁用项。
提及组件行为与导航
src/Mentions.tsx
新增 getEnabledActiveIndex、在测量启动/选项变更时重置/初始化 activeIndex 到第一个可用项;在键盘上下导航与回车选择中跳过或忽略禁用项;selectOption 增加空/禁用检查。
提及功能测试用例
tests/Mentions.spec.tsx
新增多项测试覆盖禁用项场景(Enter 跳过禁用项、全部禁用时不修改输入、箭头键跳过禁用项、options 缩减时安全处理、无选项场景)。

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DropdownMenu as DropdownMenu
    participant Mentions
    participant Options as OptionsList

    User->>DropdownMenu: 鼠标悬停某项
    DropdownMenu->>DropdownMenu: 检查项是否禁用
    alt 项目已禁用
        DropdownMenu->>DropdownMenu: 不调用 setActiveIndex
    else 项目已启用
        DropdownMenu->>DropdownMenu: 调用 setActiveIndex(index)
    end

    User->>Mentions: 按下 Arrow Up/Down
    Mentions->>Options: 请求下一个索引
    Mentions->>Mentions: 调用 getEnabledActiveIndex(offset)(跳过禁用项)
    Mentions->>Mentions: 更新 activeIndex

    User->>Mentions: 按下 Enter
    Mentions->>Mentions: 校验 current activeIndex 是否存在且非禁用
    alt 无效或为禁用项
        Mentions->>Mentions: 使用 getEnabledActiveIndex(0) 选择首个可用项
    end
    Mentions->>Mentions: 调用 selectOption 并提交选择
Loading

Estimated code review effort

🎯 3 (中等) | ⏱️ ~20 minutes

Possibly related issues

Suggested reviewers

  • zombieJ

Poem

🐰 鼠标轻点不惊跑,
箭头穿梭跳沉草,
回车只抱醒来友,
输入安稳不改掉,
提及更清爽,兔子笑 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题清晰准确地总结了主要改动:修复Mentions组件中通过键盘选择禁用选项的问题,与所有代码改动高度相关。
Linked Issues check ✅ Passed PR成功实现了问题#56934的所有要求:跳过禁用选项的键盘导航、Enter键选择第一个启用选项、禁用所有选项时不修改文本。
Out of Scope Changes check ✅ Passed 所有改动均在scope内:DropdownMenu的MenuItem悬停防护、Mentions的禁用选项处理逻辑及测试,都直接支持修复键盘交互问题。
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 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.

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

本次 PR 修复了 Mentions 组件中键盘导航和选择对 disabled 选项处理不当的问题,做得很好。主要通过引入 getEnabledActiveIndex 方法来跳过禁用项,并修正了鼠标悬停、回车选择等场景下的行为,确保了与 rc-select 的体验一致性。代码逻辑清晰,并且补充了相应的单元测试。

我在代码中发现两处逻辑可以更健壮,以处理 activeIndex 可能越界的情况。除此之外,整体修改非常棒。

@codecov
Copy link

codecov bot commented Mar 12, 2026

Codecov Report

❌ Patch coverage is 97.36842% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 98.33%. Comparing base (6f774ea) to head (4b547cd).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/Mentions.tsx 97.22% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #308      +/-   ##
==========================================
- Coverage   98.51%   98.33%   -0.18%     
==========================================
  Files           8        8              
  Lines         270      301      +31     
  Branches       65       79      +14     
==========================================
+ Hits          266      296      +30     
- Misses          4        5       +1     

☔ 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.

@zombieJ zombieJ merged commit ec60ea9 into react-component:master Mar 12, 2026
5 of 7 checks passed
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.

[BUG] Mentions: Pressing Enter Key in Mention Component Selects Disabled First Option Instead of First Available Option

2 participants