Skip to content

fix: 无障碍问题修复 #6918

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

shuningYanger
Copy link

@shuningYanger shuningYanger commented Jul 21, 2025

Summary by CodeRabbit

  • 新功能

    • 虚拟输入框内容区新增了 role="textbox" 属性,提升了无障碍访问体验。
  • 修复

    • 点击虚拟输入框首字符时,光标现在会移动到输入末尾,优化了光标定位行为。
  • 样式

    • 仅在输入框聚焦时渲染光标容器,提升界面表现。
  • 测试

    • 测试用例统一使用鼠标事件替代触摸事件,修正了光标位置和内容断言,并完善了注释说明。
  • 其他

    • 数字键盘组件的交互事件由触摸事件调整为鼠标事件,提升桌面端兼容性。
    • 代码注释由中文翻译为英文,提升可读性。

Copy link

coderabbitai bot commented Jul 21, 2025

📝 Walkthrough

Walkthrough

本次变更主要涉及 VirtualInput 组件及其测试用例,将原有的 touch 事件统一替换为 mouse 事件,修正了光标位置的断言与注释,并对部分交互细节进行了微调。此外,NumberKeyboard 组件的键盘事件也从 touch 事件切换为 mouse 事件,提升了事件处理的一致性和可访问性。

Changes

文件/分组 变更简述
src/components/virtual-input/tests/virtual-input.test.tsx 测试用例 touch 事件改为 mouse 事件,修正光标断言和注释,细化交互测试。
src/components/virtual-input/virtual-input.tsx 注释翻译与优化,首字符点击光标逻辑调整,聚焦时才渲染光标容器,补充无障碍属性。
src/components/number-keyboard/number-keyboard.tsx 所有键盘交互事件由 touch 改为 mouse 事件,confirm 键用 onClick。

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant VirtualInput
    participant NumberKeyboard

    User->>VirtualInput: mouseDown/mouseUp(输入框聚焦/点击字符)
    VirtualInput->>VirtualInput: 更新光标位置
    User->>NumberKeyboard: mouseDown/mouseUp/click(按键操作)
    NumberKeyboard->>VirtualInput: 调用输入/删除回调
    VirtualInput->>VirtualInput: 更新输入内容与光标
Loading

Estimated code review effort

2 (~15分钟)

Possibly related PRs

Suggested labels

lgtm

Suggested reviewers

  • zombieJ

Poem

小兔敲键盘,事件轻轻换,
touch 变 mouse,光标不再乱。
注释换新颜,测试更严谨,
虚拟输入框,体验又升迁。
🐰✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 008ac15 and e03d624.

📒 Files selected for processing (3)
  • src/components/number-keyboard/number-keyboard.tsx (3 hunks)
  • src/components/virtual-input/tests/virtual-input.test.tsx (19 hunks)
  • src/components/virtual-input/virtual-input.tsx (9 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/components/virtual-input/tests/virtual-input.test.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/virtual-input/virtual-input.tsx
🔇 Additional comments (4)
src/components/number-keyboard/number-keyboard.tsx (4)

176-182: 事件处理改进符合无障碍要求

onTouchStart 替换为 onMouseDown 是正确的无障碍改进,确保键盘组件能够响应鼠标事件,提升了对辅助技术的兼容性。


183-188: 事件处理逻辑保持一致

onTouchEnd 替换为 onMouseUp 后,事件处理逻辑保持不变,包括按键处理和连续清除功能的停止。这种改动提升了组件的可访问性。


230-236: 确认区域的删除键事件处理正确

确认区域中删除键的事件处理从触摸事件切换到鼠标事件,保持了与主键盘区域一致的事件处理模式。onMouseDown 启动连续清除,onMouseUp 执行删除并停止连续清除。


249-249: 确认键使用 onClick 事件更符合语义

确认键从 onTouchEnd 改为 onClick 是一个很好的改进,onClick 事件在语义上更适合确认操作,并且能够同时处理鼠标点击和键盘激活,进一步提升了无障碍体验。

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • 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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

github-actions bot commented Jul 21, 2025

Preview is ready

@dosubot dosubot bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Jul 21, 2025
@coderabbitai coderabbitai bot requested a review from zombieJ July 21, 2025 11:07
@shuningYanger shuningYanger marked this pull request as draft July 21, 2025 11:11
Copy link

@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: 3

🧹 Nitpick comments (1)
src/components/virtual-input/tests/virtual-input.test.tsx (1)

437-447: 存在注释掉的测试代码

这段测试代码被注释掉了,看起来是测试在位置 0 输入小数点的场景。是否需要实现这个测试用例?

需要我帮助完成这个测试用例吗?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b7e04e8 and 008ac15.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • src/components/virtual-input/demos/demo1.tsx (2 hunks)
  • src/components/virtual-input/tests/virtual-input.test.tsx (7 hunks)
  • src/components/virtual-input/virtual-input.tsx (7 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Socket Security: Pull Request Alerts
🔇 Additional comments (15)
src/components/virtual-input/demos/demo1.tsx (5)

3-5: 导入和正则表达式定义合理

React hooks 的导入和货币输入的正则表达式定义都很合适。


8-19: 第一个演示正确展示了可移动光标功能

添加了状态管理和 ref,正确设置了 cursor='movable' 属性。


30-36: 新增的静态光标演示有助于对比

这个演示很好地展示了默认的静态光标行为,与可移动光标形成对比。


61-81: 货币输入演示实现完善

实现了完整的货币输入验证逻辑:

  • 正确处理以小数点开头的输入
  • 移除前导零
  • 使用正则表达式验证格式
  • 大字体样式适合金额展示

82-82: 用于测试的垂直空间

这个大的垂直空间可能是为了测试滚动场景下的触摸交互。

src/components/virtual-input/tests/virtual-input.test.tsx (5)

7-106: 测试基础设施实现完善

新增的辅助函数和设置为光标交互测试提供了良好的基础:

  • clickSiblingElements 能精确模拟点击位置
  • makeTouchEvent 正确模拟触摸事件
  • 模拟固定字符宽度确保测试一致性

218-285: 受控组件光标位置测试全面

测试覆盖了受控组件的光标交互:

  • 键盘输入后的光标位置
  • 点击重新定位光标
  • 在特定位置删除字符
  • 所有断言都正确

501-613: 触摸拖动光标测试实现优秀

测试全面覆盖了触摸拖动功能:

  • 模拟真实的触摸拖动场景
  • 验证拖动时的视觉反馈
  • 测试边界条件和阈值
  • 测试超时行为

615-681: 静态光标模式测试完善

正确验证了在默认静态模式下:

  • 触摸移动无法改变光标位置
  • 点击无法改变光标位置

324-328: 测试注释与实际行为不一致

注释说"点击 '1' 左侧,光标位置应该在值的末尾",但断言期望光标仍在位置 3。这可能是注释错误或测试逻辑问题。

建议修正注释或测试逻辑:

-    // click '1' left side in inputbox, caret position should be value end
+    // click '1' left side in inputbox, caret position should remain at end (3)

Likely an incorrect or invalid review comment.

src/components/virtual-input/virtual-input.tsx (5)

102-114: 光标位置更新逻辑实现正确

正确处理了受控组件的光标位置:

  • 当值符合预期时保持相对位置
  • 当父组件修改值时重置到末尾

147-166: 键盘输入处理逻辑完善

正确实现了光标位置的输入和删除:

  • 在光标位置插入字符
  • 删除光标前的字符
  • 光标在起始位置时阻止删除

194-199: 点击第一个字符的特殊处理逻辑

index === 0 时,光标被设置到末尾而不是开头。这个行为是否符合预期?通常点击第一个字符应该将光标放在开头或第一个字符后。

请确认这个特殊处理的设计意图。


212-262: 触摸拖动实现完善

触摸事件处理逻辑合理:

  • 20px 的触摸阈值适合移动端
  • 基于字符宽度的移动计算准确
  • 边界检查防止无效位置
  • 超时机制处理未完成的手势

314-333: 清除按钮实现改进

正确处理了禁用状态和焦点管理:

  • 禁用时隐藏清除按钮
  • 防止点击时失去焦点
  • 保持无障碍属性

Comment on lines 95 to 101
useEffect(() => {
// 记录单个字符的宽度,用于光标移动时的计算
if (charRef.current) {
charWidthRef.current = charRef.current.getBoundingClientRect().width
}
}, [value])

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

字符宽度测量需要空值检查

当值为空时,charRef.current 可能为 null。

添加空值检查:

   useEffect(() => {
     // 记录单个字符的宽度,用于光标移动时的计算
-    if (charRef.current) {
+    if (charRef.current && value.length > 0) {
       charWidthRef.current = charRef.current.getBoundingClientRect().width
     }
   }, [value])
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
// 记录单个字符的宽度,用于光标移动时的计算
if (charRef.current) {
charWidthRef.current = charRef.current.getBoundingClientRect().width
}
}, [value])
useEffect(() => {
// 记录单个字符的宽度,用于光标移动时的计算
- if (charRef.current) {
+ if (charRef.current && value.length > 0) {
charWidthRef.current = charRef.current.getBoundingClientRect().width
}
}, [value])
🤖 Prompt for AI Agents
In src/components/virtual-input/virtual-input.tsx around lines 95 to 101, the
useEffect hook measures character width but does not safely handle the case when
charRef.current is null. Add a null check before accessing
charRef.current.getBoundingClientRect() to ensure the code only runs when
charRef.current is not null, preventing potential runtime errors.

Comment on lines 280 to 283
ref={contentRef}
role='textbox'
tabIndex={mergedProps.disabled ? undefined : 0}
aria-disabled={mergedProps.disabled}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

存在重复的无障碍属性

role="textbox"tabIndex 同时出现在根元素和内容元素上,这可能导致屏幕阅读器的混淆。

建议只在根元素上保留这些属性:

         <div
           className={`${classPrefix}-content`}
           ref={contentRef}
-          role='textbox'
-          tabIndex={mergedProps.disabled ? undefined : 0}
           aria-disabled={mergedProps.disabled}
           aria-label={mergedProps.placeholder}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ref={contentRef}
role='textbox'
tabIndex={mergedProps.disabled ? undefined : 0}
aria-disabled={mergedProps.disabled}
<div
className={`${classPrefix}-content`}
ref={contentRef}
aria-disabled={mergedProps.disabled}
aria-label={mergedProps.placeholder}
🤖 Prompt for AI Agents
In src/components/virtual-input/virtual-input.tsx around lines 280 to 283, the
accessibility attributes role="textbox" and tabIndex are duplicated on both the
root and content elements, which can confuse screen readers. Remove these
attributes from the content element and keep them only on the root element to
ensure proper accessibility semantics.

Copy link

pkg-pr-new bot commented Jul 22, 2025

npm i https://pkg.pr.new/ant-design/ant-design-mobile/antd-mobile@6918

commit: e03d624

Copy link

codecov bot commented Jul 22, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 92.82%. Comparing base (b7e04e8) to head (fd3ef01).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #6918   +/-   ##
=======================================
  Coverage   92.82%   92.82%           
=======================================
  Files         336      336           
  Lines        7271     7275    +4     
  Branches     1832     1833    +1     
=======================================
+ Hits         6749     6753    +4     
  Misses        486      486           
  Partials       36       36           

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

@shuningYanger shuningYanger marked this pull request as ready for review July 23, 2025 07:34
@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. labels Jul 23, 2025
@shuningYanger shuningYanger marked this pull request as draft July 23, 2025 07:35
@shuningYanger shuningYanger marked this pull request as ready for review July 23, 2025 07:36
@shuningYanger shuningYanger marked this pull request as draft July 23, 2025 07:36
@coderabbitai coderabbitai bot added the lgtm This PR has been approved by a maintainer label Jul 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug feature lgtm This PR has been approved by a maintainer size:L This PR changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant