Skip to content

Conversation

@zkt2002
Copy link

@zkt2002 zkt2002 commented Jan 9, 2026

Summary by CodeRabbit

  • Bug Fixes
    • 优化了对话框的关闭交互检测机制。
    • 修复了从对话框内容拖拽到遮罩区域时对话框意外关闭的问题。

- 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

演练

重构了 Dialog 组件的关闭交互逻辑,从基于内容元素的点击追踪改为基于遮罩的点击追踪。通过新增 mouseDownOnMaskRefonWrapperMouseDown 处理器,实现对拖拽行为的区分,防止从内容区域拖拽到遮罩时误触发关闭。

变更

层级 / 文件 总结
Dialog 交互模型重构
src/Dialog/index.tsx
移除基于内容的点击追踪逻辑(contentClickRef、contentTimeoutRef、onContentMouseDown、onContentMouseUp),引入基于遮罩的追踪机制。新增 mouseDownOnMaskRef 标志和 onWrapperMouseDown 处理器,于包装元素层捕获鼠标按下事件;更新 onWrapperClick 逻辑,仅在点击目标为包装元素且 mouseDownOnMaskRef 为 true 时触发关闭;移除传递给 Content 组件的 onMouseDown/onMouseUp props。
测试场景更新
tests/index.spec.tsx
调整遮罩关闭交互测试用例,改为依次执行 mouseDown 和 mouseUp 事件序列。新增测试用例"should not close when dragging from content to mask",验证从内容区域拖拽至遮罩时不会触发关闭回调。

序列图

sequenceDiagram
    participant User
    participant Wrapper
    participant Dialog
    participant Mask
    participant Content

    rect rgba(100, 150, 200, 0.5)
    Note over User,Content: 正常关闭流程(点击遮罩)
    User->>Wrapper: mouseDown on mask
    activate Wrapper
    Wrapper->>Dialog: onWrapperMouseDown()
    Dialog->>Dialog: mouseDownOnMaskRef.current = true
    deactivate Wrapper

    User->>Wrapper: click on mask
    activate Wrapper
    Wrapper->>Dialog: onWrapperClick()
    alt mouseDownOnMaskRef.current == true
        Dialog->>Dialog: trigger onInternalClose()
    else
        Dialog->>Dialog: no action
    end
    Dialog->>Dialog: reset mouseDownOnMaskRef.current = false
    deactivate Wrapper
    end

    rect rgba(200, 100, 100, 0.5)
    Note over User,Content: 拖拽防护流程(从内容拖至遮罩)
    User->>Content: mouseDown on content
    activate Content
    Content->>Dialog: mouseDownOnMaskRef = false
    deactivate Content

    User->>Mask: mouseUp on mask
    activate Mask
    Mask->>Dialog: onWrapperClick()
    alt mouseDownOnMaskRef.current == false
        Dialog->>Dialog: no action (drag detected)
    end
    deactivate Mask
    end
Loading

预估审查工作量

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

建议审查人

  • 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

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.91%. Comparing base (10b7c44) to head (f4c2f1d).
⚠️ Report is 4 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #543      +/-   ##
==========================================
+ Coverage   98.42%   98.91%   +0.48%     
==========================================
  Files           8        8              
  Lines         191      185       -6     
  Branches       67       70       +3     
==========================================
- Hits          188      183       -5     
+ 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.
@zkt2002
Copy link
Author

zkt2002 commented Jan 29, 2026

能合并了嘛大佬 @zombieJ

@zombieJ
Copy link
Member

zombieJ commented Jan 30, 2026

@gemini-code-assist Pls help to CR again.

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 addresses the issue where dragging from the dialog content to the mask would unintentionally trigger the dialog's close event. The solution involves tracking the mousedown event on the wrapper to ensure that the onClose callback is only invoked if both the mousedown and subsequent mouseup/click events originate from the mask itself. The previous contentClickRef logic has been removed, simplifying the event handling. Additionally, comprehensive unit tests have been added in a new file, tests/mask-closable.spec.tsx, to specifically cover the mask close behavior, including scenarios where dragging from content to mask should not trigger a close. This is a well-implemented and thoroughly tested fix.

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