Skip to content

fix(interact-outside): handle focus-outside detection inside shadow roots#3093

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/fix-onfocusoutside-shadow-root
Draft

fix(interact-outside): handle focus-outside detection inside shadow roots#3093
Copilot wants to merge 2 commits intomainfrom
copilot/fix-onfocusoutside-shadow-root

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 21, 2026

📝 Description

Focus transitions triggered by keyboard navigation inside a shared shadow root were not reaching the existing global focusin listeners, so onFocusOutside did not fire and dismissable widgets could remain open.
This update makes shadow-root focus transitions observable to interact-outside without changing public API shape.

  • Focus listener coverage
    • Register focusin on the component’s rootNode when the tracked node is inside a shadow root.
  • Deferred focus handling stability
    • Capture composedPath() before deferred execution so the original focus event target is preserved.
  • Regression protection
    • Add a focused unit test for focus movement from tracked content to a sibling element within the same shadow root.
if (!isTouchDevice()) {
  cleanups.add(addDomEvent(doc, "focusin", onFocusin, true))
  cleanups.add(parentWin.addEventListener("focusin", onFocusin, true))
  cleanups.add(frames.addEventListener("focusin", onFocusin, true))
  if (isInShadowRoot) {
    cleanups.add(addDomEvent(node?.getRootNode(), "focusin", onFocusin, true))
  }
}

⛳️ Current behavior (updates)

When a dismissable element (e.g. popover/menu) is rendered in a shadow root, tabbing focus to another element in the same shadow root can fail to trigger onFocusOutside, leaving the element open.

🚀 New behavior

onFocusOutside is now detected for keyboard focus transitions within the same shadow root, so dismissable elements correctly react to outside focus in shadow-DOM contexts.

💣 Is this a breaking change (Yes/No):

No

📝 Additional Information

No external dependencies were added. The change is scoped to @zag-js/interact-outside internals plus a targeted regression test.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 21, 2026

⚠️ No Changeset found

Latest commit: 42e7c84

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copilot AI linked an issue Apr 21, 2026 that may be closed by this pull request
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
zag-nextjs Ready Ready Preview Apr 21, 2026 5:44am
zag-solid Ready Ready Preview Apr 21, 2026 5:44am
zag-svelte Ready Ready Preview Apr 21, 2026 5:44am
zag-vue Ready Ready Preview Apr 21, 2026 5:44am
zag-website Ready Ready Preview Apr 21, 2026 5:44am

Request Review

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.

onFocusOutside is not detected properly in a shadow root

2 participants