⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content

Conversation

@zkt2002
Copy link

@zkt2002 zkt2002 commented Jan 9, 2026

Summary by CodeRabbit

发布说明

  • Bug 修复

    • 优化了对话框遮罩关闭判定:改用按下/抬起结合点击的判定并在可见时重置按下状态,避免拖拽或误触导致的意外关闭,提升 maskClosable 的一致性与可靠性。
  • 测试

    • 新增并完善遮罩关闭行为单元测试,覆盖遮罩点击关闭、从内容到遮罩或从遮罩到内容的拖拽不触发关闭等场景。

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

- Use event capture to track `mousedown` and `mouseup` on the wrapper
- Ensure close is only triggered when the click action fully occurs on the mask
- Fix issue where dragging from content to mask (e.g. slider or text selection) triggers unintended close
Closes ant-design/ant-design#56348
@coderabbitai
Copy link

coderabbitai bot commented Jan 9, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

将 Dialog 的点击遮罩关闭逻辑由基于内容的按压/超时检测替换为基于 wrapper 的鼠标按下追踪(mouseDownOnMaskRef),并相应更新与新增单元测试以覆盖完整鼠标交互与拖拽场景。

Changes

Cohort / File(s) 变更摘要
对话框交互逻辑
src/Dialog/index.tsx
移除基于 content 的 click 计时器与相关 refs/onMouseDown/onMouseUp;新增 mouseDownOnMaskRef 与 wrapper 级别的 onWrapperMouseDown(在 wrapper 上绑定 onMouseDown),在 onWrapperClick 仅当点击目标为 wrapper 且 mouseDownOnMaskRef 为真时触发内部关闭;在对话框显示时重置 ref。
调整现有测试
tests/index.spec.tsx
将遮罩关闭测试由单次 click 改为完整交互序列 mouseDownmouseUpclick,保留定时器推进与 onClose 断言。
新增遮罩行为测试
tests/mask-closable.spec.tsx
新增三项用例覆盖:遮罩点击可关闭、从内容拖拽到遮罩不触发关闭、从遮罩拖拽到内容不触发关闭;使用伪定时器并通过 DOM 查询定位 wrapper 元素。

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Wrapper as Wrapper/遮罩
    participant Dialog as Dialog 组件
    participant Content as Content/内容

    User->>Wrapper: mouseDown
    Wrapper->>Dialog: onWrapperMouseDown (mouseDownOnMaskRef = true)
    User->>Wrapper: mouseUp
    User->>Wrapper: click
    Wrapper->>Dialog: onWrapperClick (检查 target 为 wrapper 且 mouseDownOnMaskRef)
    alt 满足关闭条件
        Dialog->>Dialog: onInternalClose()
        Dialog->>User: 调用 onClose
    else 不满足(拖拽等)
        Dialog->>Dialog: 不触发关闭
    end
Loading

Estimated code review effort

🎯 3 (中等) | ⏱️ ~20 分钟

建议审查者

  • zombieJ

诗歌

🐰 轻敲遮罩小脚印,按住放开都记心,
一点标志保安宁,拖拽误关不用惊,
测试齐备声声稳,Dialog 安好又一春。

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确总结了主要变更:通过新的鼠标事件跟踪机制,防止从对话框内容拖动到遮罩层时触发关闭操作。

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment


📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fcb258d and f4c2f1d.

📒 Files selected for processing (2)
  • src/Dialog/index.tsx
  • tests/mask-closable.spec.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/mask-closable.spec.tsx
🔇 Additional comments (5)
src/Dialog/index.tsx (5)

113-113: LGTM!

命名清晰,准确反映了该 ref 的用途:跟踪 mousedown 事件是否发生在遮罩上。


120-127: 逻辑正确,有效解决拖拽关闭问题。

通过同时检查 mouseDownOnMaskRef.current 和 click 事件的 target,确保只有当完整的点击动作(mousedown + click)都发生在遮罩上时才触发关闭,完美解决了从对话框内容拖拽到遮罩意外关闭的问题。


130-133: 实现简洁,采纳了之前的审查建议。

使用直接布尔赋值,代码简洁明了。同时遵循了 zombieJ 的建议,使用冒泡事件而非捕获事件,避免了潜在的事件冲突。


136-139: 正确重置 ref 状态,避免跨会话污染。

在对话框变为可见时重置 mouseDownOnMaskRef.current,有效防止了之前审查中指出的状态污染问题:即对话框关闭后重新打开时,旧的 mousedown 状态可能导致意外的关闭行为。


180-183: LGTM!

事件绑定正确,与 onClick 配合实现完整的点击追踪。

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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.

@vercel
Copy link

vercel bot commented Jan 9, 2026

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

A member of the Team first needs to authorize it.

@gemini-code-assist
Copy link

Summary of Changes

Hello @zkt2002, 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 addresses a critical usability bug in the Dialog component where dragging operations that started within the dialog content and ended on the mask would inadvertently close the dialog. The changes introduce a more robust event handling mechanism that precisely determines if a mask click is intentional, thereby preventing premature dialog dismissal and improving the overall user experience.

Highlights

  • Bug Fix: Unintended Dialog Closure: Resolves an issue where dragging the mouse from the dialog's content area onto the mask would erroneously trigger the dialog to close, preventing unwanted interruptions during user interaction.
  • Enhanced Mask Click Detection: Implements a more precise mechanism for detecting mask clicks by tracking both "mousedown" and "mouseup" events using event capturing on the dialog wrapper. This ensures the dialog only closes if the entire click action originates and ends on the mask.
  • Refactored Event Handling: Removes previous contentClickRef and contentTimeoutRef logic, replacing it with mouseDownOnMaskRef and mouseUpOnMaskRef to streamline event state management for mask interactions.
  • Comprehensive Test Coverage: Introduces a new dedicated test file (mask-closable.spec.tsx) with specific scenarios to validate the corrected mask closing behavior, including tests for dragging from content to mask and mask to content.

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

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 effectively resolves an issue where dragging from the dialog's content to its mask would unintentionally close the dialog. The new approach, which tracks mousedown and mouseup events in the capture phase, is a robust and clean solution. It correctly ensures that the dialog only closes when a complete click action occurs on the mask. The removal of the previous setTimeout-based logic simplifies the component, and the addition of comprehensive unit tests for various drag scenarios is a great enhancement to ensure the fix is solid. I have a couple of minor suggestions to further simplify the new event handlers.

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: 1

🤖 Fix all issues with AI agents
In @src/Dialog/index.tsx:
- Around line 113-114: Reset mouseDownOnMaskRef and mouseUpOnMaskRef when the
dialog opens (or on close) to avoid stale cross-session state; inside the Dialog
component add a useEffect watching the open/visible prop (the same prop used to
control mounting) and set mouseDownOnMaskRef.current = false and
mouseUpOnMaskRef.current = false whenever the dialog becomes visible (or when it
unmounts/closes) so previous mouse events do not leak into the next session.
🧹 Nitpick comments (1)
src/Dialog/index.tsx (1)

134-148: 建议添加注释说明遮罩点击追踪的逻辑

这两个捕获阶段处理器实现了新的遮罩点击追踪机制,逻辑正确。但为了提高代码可维护性,建议添加注释说明:

  • 为什么使用捕获阶段(Capture)
  • 为什么检查 e.target === wrapperRef.current 而不是使用 e.currentTarget
  • 这种机制如何防止拖拽操作触发关闭
参考注释示例
+  // Use capture phase to track mouse events on the mask element before they bubble.
+  // Check e.target (the actual clicked element) to ensure the event occurred
+  // directly on the wrapper/mask, not on any child elements.
   function onModulesMouseDownCapture(e: React.MouseEvent) {
     if (e.target === wrapperRef.current) {
       mouseDownOnMaskRef.current = true;
     } else {
       mouseDownOnMaskRef.current = false;
     }
   }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 10b7c44 and da17a42.

📒 Files selected for processing (3)
  • src/Dialog/index.tsx
  • tests/index.spec.tsx
  • tests/mask-closable.spec.tsx
🔇 Additional comments (6)
src/Dialog/index.tsx (2)

123-128: 逻辑正确,有效修复了拖拽触发关闭的问题

新的条件判断确保只有当完整的点击序列(mouseDown + mouseUp + click)都发生在遮罩上时才触发关闭,这正确解决了从内容拖拽到遮罩导致意外关闭的问题。实现思路清晰合理。


198-199: 捕获处理器集成正确

捕获事件处理器已正确附加到包装器元素上,与 onClick 处理器配合工作以实现新的遮罩点击追踪机制。

tests/index.spec.tsx (1)

176-179: 测试更新正确反映了新的交互模型

测试已正确更新为使用完整的鼠标交互序列(mouseDown → mouseUp → click),与新的遮罩点击追踪实现保持一致。

tests/mask-closable.spec.tsx (3)

15-34: 遮罩点击关闭测试实现正确

测试正确验证了在遮罩上执行完整点击序列时对话框会关闭的行为。防御性的空值检查(第 28 行)也很好。


36-60: 关键测试用例:正确验证拖拽场景

此测试用例验证了 PR 要解决的核心问题 - 从内容拖拽到遮罩时不应触发关闭。测试逻辑准确模拟了用户拖拽操作(如滑动滑块或选择文本),确保对话框不会意外关闭。


62-90: 反向拖拽场景测试完整

测试覆盖了从遮罩拖拽到内容的场景,确保这种情况也不会触发关闭。第 83-86 行的注释体现了对真实浏览器行为的深入思考,有助于理解测试意图。

@codecov
Copy link

codecov bot commented Jan 9, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.94%. Comparing base (10b7c44) to head (fcb258d).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #543      +/-   ##
==========================================
+ Coverage   98.42%   98.94%   +0.51%     
==========================================
  Files           8        8              
  Lines         191      190       -1     
  Branches       67       70       +3     
==========================================
  Hits          188      188              
+ Misses          3        2       -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.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a bug where the dialog would unintentionally close when users drag from content to mask (e.g., when using a slider or selecting text). The fix replaces a timeout-based click tracking mechanism with a more precise event capture approach that tracks where mouseDown and mouseUp events occur.

Key Changes:

  • Introduced capture-phase event handlers to accurately track mouseDown and mouseUp locations on the wrapper element
  • Removed the previous timeout-based content click tracking mechanism
  • Added comprehensive test coverage for the drag-and-drop scenarios

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
src/Dialog/index.tsx Replaced timeout-based content click tracking with capture-phase mouseDown/mouseUp tracking on the wrapper element; removed cleanup effect for the old timeout mechanism
tests/index.spec.tsx Updated the "mask to close" test to fire mouseDown and mouseUp events before click to match the new behavior
tests/mask-closable.spec.tsx Added comprehensive test suite covering mask closure scenarios: clicking on mask, dragging from content to mask, and dragging from mask to content

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Use bubbling `onMouseDown` to track if the click originated from the mask.
- Only trigger close in `onClick` if both mousedown and click targets are the wrapper.
- Reset tracking refs when dialog becomes visible to prevent state pollution.
- Remove capture listeners to avoid potential event conflicts.
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.

Modal中滑动Slider在Mask层松开会关闭Modal

2 participants