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

Walkthrough

将 Dialog 的遮罩关闭逻辑由基于内容的点击计时器改为基于遮罩鼠标事件的双引用追踪(mouseDownOnMaskRef、mouseUpOnMaskRef),新增 wrapper 捕获事件并更新相关单元测试以覆盖拖拽与完整鼠标交互场景。

Changes

Cohort / File(s) 变更摘要
对话框交互逻辑更新
src/Dialog/index.tsx
mouseDownOnMaskRefmouseUpOnMaskRef 替换原有基于内容的点击计时器;添加 onWrapperMouseDownCapture / onWrapperMouseUpCapture 并通过 onMouseDownCapture/onMouseUpCapture 挂载到 wrapper;在 onWrapperClick 中仅当 target 为 wrapper 且两个 ref 为真时触发关闭;移除 Content 上的 onMouseDown/onMouseUp 与超时清理 effect。
测试用例调整
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: onWrapperMouseDownCapture (mouseDownOnMaskRef = true)
    User->>Wrapper: mouseUp
    Wrapper->>Dialog: onWrapperMouseUpCapture (mouseUpOnMaskRef = true)
    User->>Wrapper: click
    Wrapper->>Dialog: onWrapperClick (检查 target 为 wrapper && mouseDownOnMaskRef && mouseUpOnMaskRef)
    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 PR标题准确反映了主要变更内容:通过改进点击检测逻辑来防止内容拖拽到遮罩时触发关闭。

✏️ 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 8cbf1c5 and fcb258d.

📒 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 (2)
  • tests/mask-closable.spec.tsx
  • src/Dialog/index.tsx

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.

className={clsx(`${prefixCls}-wrap`, wrapClassName, modalClassNames?.wrapper)}
ref={wrapperRef}
onClick={onWrapperClick}
onMouseDownCapture={onWrapperMouseDownCapture}
Copy link
Member

Choose a reason for hiding this comment

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

不要用 capture,会导致很多非预期的冲突。可以考虑在 mouseDown 的时候记录一下是否点击在 mask,click 的时候对比一下 target 就行了

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