[RAC] Stacked modals: closing overlay dismisses the one beneath it during its exit animation

未关闭
#10,291 4 条评论 1 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
3/5
预计耗时
1-2 天
新手友好度
68/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
冷清
技术栈
react, typescript

调研方向

从 packages/react-aria/src/overlays/useOverlay.ts 开始,重点查看 visibleOverlays 堆栈和外部交互处理,然后比较 packages/react-aria-components/src/Modal.tsx 中的挂载行为。在链接的 CodeSandbox 中复现模态框堆叠的情况;完成标准是,正在退出的顶部模态框在卸载之前一直是交互的所有者,因此底层模态框不会被关闭。

由索引模型根据 Issue 内容生成。

描述

needs investigation
Provide a general summary of the issue here

With stacked modals (a Modal/ModalOverlay opened on top of another), closing the top modal while it has an exit animation can cause the modal underneath it to be dismissed by an outside-click that actually landed on the still-animating top modal.

🤔 Expected Behavior?

A modal that's still mounted and visually on top (mid exit-animation) should keep owning pointer interactions that land on it. Only a click genuinely outside all modals should dismiss the one beneath.

😯 Current Behavior

useOverlay only lets the topmost entry in its visibleOverlays stack react to outside interactions, but stack membership is keyed on isOpen — an overlay is spliced out the instant it starts closing:

https://github.com/adobe/react-spectrum/blob/54d1b2b3c8c2a84fd54cccadca2d9cb5d742b943/packages/react-aria/src/overlays/useOverlay.ts#L80-L91

react-aria-components, however, keeps the closing overlay mounted (backdrop + content, still on top, still hit-testable) until its exit animation finishes:

https://github.com/adobe/react-spectrum/blob/54d1b2b3c8c2a84fd54cccadca2d9cb5d742b943/packages/react-aria-components/src/Modal.tsx#L205-L206

So during the exit animation the top overlay is gone from the stack but still physically covers the one beneath. A pointer interaction landing on it is, for the overlay beneath, "outside", and since that overlay is now visibleOverlays[last], the handler fires onHide() and closes it:

https://github.com/adobe/react-spectrum/blob/54d1b2b3c8c2a84fd54cccadca2d9cb5d742b943/packages/react-aria/src/overlays/useOverlay.ts#L94-L126

The "only the topmost visible overlay reacts to outside interactions" invariant is silently broken for any overlay mid exit-animation.

💁 Possible Solution

Keep an overlay in visibleOverlays until it actually unmounts, so it stays topmost as long as it's physically on top.

🔦 Context

We have a picker modal inside a dialog (pick an item, the picker closes, click something on the dialog, which lands on the exiting picker). Worked around it with a shouldCloseOnInteractOutside on the outer modal, ignoring interactions whose target is inside a modal.

🖥️ Steps to Reproduce
  1. Stack dismissable ModalOverlay A, then B on top, both with isExiting exit animations.
  2. Close B
  3. While B is closing, click again
  4. A will close because clicking on the exiting B is considered outside A

Code sandbox: https://codesandbox.io/p/sandbox/dvnjy5

https://github.com/user-attachments/assets/58b286f1-6ab7-40cf-9491-c0efb822a848

Version

react-aria-components 1.19.0 (react-aria 3.50.0)

What browsers are you seeing the problem on?

Chrome

If other, please specify.

No response

What operating system are you using?

macOS

🧢 Your Company/Team

No response

🕷 Tracking Issue

No response

主要语言
TypeScript
星标
16k
派生
1.6k
平均合并
3 天 9 小时
30 天内合并 PR
45

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

adobe/react-spectrum 的其他 Issue

查看 adobe/react-spectrum 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。