Skip to content

Throw in renderWebChat() on React 16 for an element inside a shadow root - #5982

Merged
Eugene (OEvgeny) merged 8 commits into
mainfrom
OEvgeny/fix-react-16-shadow-dom
Oct 30, 2026
Merged

Eugene (OEvgeny) merged 8 commits into
mainfrom
OEvgeny/fix-react-16-shadow-dom

Conversation

@OEvgeny

@OEvgeny Eugene (OEvgeny) commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Related to #5315

Changelog Entry

Changed

  • Made renderWebChat() on React 16 throw for an element inside a shadow root, where clicks and typing were ignored, related to #5315, in PR #5982, by @OEvgeny

Description

On React 16, the default in webchat.js, Web Chat in an element inside a shadow root ignored every click and keystroke: React 16 listens on the document, which sees the shadow host as the target. renderWebChat() now throws there, suggesting the shadow root or React 17+.

Design

  • Throw instead of a hidden portal with React 16's event handlers in the shadow root: the shadow root, or React 17+, works without it.
  • Not covered: <ReactWebChat> rendered by the host on React 16.

Specific Changes

  • renderWebChat.tsx: throw on React 16 for an element inside a shadow root

  • SuggestedActions.tsx: pass stylesRoot to the carousel, unstyled in a shadow root

  • customElement/shadowRoot.react16.throw.html: the error, then rendered into the shadow root

  • customElement/shadowRoot.html: React 18 instead of 16

  • shadowRoot.interact.renderIntoShadowRoot.html (React 16), shadowRoot.interact.react18.html: type and send, click a suggested action

  • I have added tests and executed them locally

  • I have added .changelog/<PR#>-<slug>.md

  • I have updated documentation

Review Checklist

This section is for contributors to review your work.

  • Accessibility reviewed (tab order, content readability, alt text, color contrast)
  • Browser and platform compatibilities reviewed
  • CSS styles reviewed (minimal rules, no z-index)
  • Documents reviewed (docs, samples, live demo)
  • Internationalization reviewed (strings, unit formatting)
  • package.json and package-lock.json reviewed
  • Security reviewed (no data URIs, check for nonce leak)
  • Tests reviewed (coverage, legitimacy)

Eugene Olonov added 4 commits October 29, 2026 11:02
React 16 listens to events on the document unless the container is a
document or a document fragment. Inside a shadow root, the document gets
events retargeted to the shadow host, so the bundled React DOM 16.8.6
ignored every click and keystroke. renderWebChat() now renders a hidden
portal into the shadow root with a no-op handler for every React 16
event, so React 16 also listens on the shadow root.
The carousel of suggested actions put its react-film styles into the
document head, so suggested actions inside a shadow root lost their
carousel layout and showed a list bullet.
Comment thread packages/bundle/src/renderWebChat.tsx Outdated
Comment thread packages/bundle/src/private/react16EventListenerProps.ts Outdated
@OEvgeny Eugene (OEvgeny) changed the title Fix renderWebChat() ignoring clicks and typing inside a shadow root on React 16 Throw in renderWebChat() on React 16 for an element inside a shadow root Oct 30, 2026
@OEvgeny
Eugene (OEvgeny) marked this pull request as ready for review October 30, 2026 07:00
Copilot AI balanced review requested due to automatic review settings October 30, 2026 07:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

);
}

const rootNode = elementOrRoot.getRootNode?.();

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Does this trip the check if passed the element's shadow root where the element is already inside another shadow root?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

No: ShadowRoot.getRootNode() returns the shadow root itself however deep its host is nested, so rootNode === elementOrRoot skips the check, and React 16 listens on that inner shadow root, where the events bubble. I tested it locally rather than pushing onto the approved head: a unit test (nested shadow root renders, an element inside it throws) and an html2 test rendering into a shadow root nested in another one that types, sends and clicks a suggested action (3 of 3 runs, same snapshots as the non-nested test; an element inside that shadow root throws, and with the check bypassed it ignores typing as expected); I can send both as a follow-up after this merges.

@OEvgeny
Eugene (OEvgeny) enabled auto-merge (squash) October 30, 2026 07:22
@OEvgeny
Eugene (OEvgeny) merged commit 3955300 into main Oct 30, 2026
50 of 61 checks passed
@OEvgeny
Eugene (OEvgeny) deleted the OEvgeny/fix-react-16-shadow-dom branch October 30, 2026 07:32
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.

3 participants