Skip to content

Conversation

@alirezamirian
Copy link
Contributor

@alirezamirian alirezamirian commented Dec 17, 2025

When working with WYSIWYG editors or similar components that mutate the dom, the order of dom mutations could be in a way that the mutation observer is called with mutation records for nodes that are no longer in the dom, but have children inside the visible element. More specifically, when an element is reparented during the dom mutations, the mutation record with the old parent still appears in the list of changes, resulting in a change where change.target is not connected to the document, but it contains addedNodes that are connected (to a new parent) and should not be hidden.

This change adds a safe-guard for such cases, by checking if the target element is connected, as otherwise it will be considered outside the currently visible elements.

Closes #9364

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

🧢 Your Project:

@alirezamirian
Copy link
Contributor Author

Adding a simple test case without using ReactQuill is a little tricky. let me know if you think it's a must to have it covered by a test case and I'll make another attempt.

Copy link
Member

@snowystinger snowystinger left a comment

Choose a reason for hiding this comment

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

I think it might be good to do a little more digging to make a test case if you don't mind.

I think you just need to append a child, then remove it, then trigger the mutation observer, then append it again and trigger the mutation observer again.

Might be worth investigating if Quill has a bug, because I'm not sure why it's doing this.

@alirezamirian
Copy link
Contributor Author

alirezamirian commented Dec 19, 2025

@snowystinger I was a little skeptical if the way MutationObserver batches changes would be similar enough in jsdom to a real browser, but it turns out it is. Added a test case, which also helped me better understand what exactly the reproduction scenario is. I did verify that the test fails without the change and passes with it.

When working with WYSIWYG editors or similar components that mutate the dom, the order or dome mutations could be in a way that dom mutation observer is called for elements that are not yet appended to the modal dom at the time MutationObserver callback is called.

This change adds a safe-guard for such cases, by checking if the target element is connected, as otherwise it will be considered outside the currently visible elements.
Copy link
Member

@snowystinger snowystinger left a comment

Choose a reason for hiding this comment

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

Thanks so much for determining how to make a test for this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ariaHideOutside sets inert on elements within the visible nodes

2 participants