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

オープン
#10,291 コメント 4 件 リアクション 1 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
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
平均マージ
2日 17時間
マージ済み PR(30日)
41

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

adobe/react-spectrum のほかの issue

adobe/react-spectrum の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。