mirror of
https://github.com/chatwoot/chatwoot.git
synced 2026-06-04 21:02:35 +08:00
2.0 KiB
2.0 KiB
Modal teleport target escapes shadow DOM in embedded mode
Context
- Vue components are exported as custom elements for React, rendered inside a shadow DOM.
- The modal component teleports its content; when it teleports to
document.body, it leaves the shadow DOM and loses styles.
Relevant files
app/javascript/react-components/src/vue-components/ChatwootMessageListWebComponent.vue- CE wrapper rendered inside the shadow root.
- Currently includes both
#cw-app-root(MessageList) and#cw-modal-root(intended modal host) inside the shadow DOM.
app/javascript/dashboard/components/Modal.vue- Modal component using
<Teleport>. - Has logic to resolve the teleport target using
getRootNodeand a fallback todocument.body.
- Modal component using
- Entry/UI setup:
app/javascript/entrypoints/ui.jsmounts the Vue app in non-CE mode (body teleport is fine there).
Current behavior
- In embedded/isolated mode (
window.__WOOT_ISOLATED_SHELL__is true), the modal still teleports todocument.bodyinstead of the shadow DOM. - Because the modal node ends up in
body, CE-injected styles do not apply; the modal appears unstyled.
Desired behavior
- When running inside the custom element (shadow DOM), the modal should teleport to
#cw-modal-rootinside that shadow root (the element already exists in the CE wrapper). - Only fall back to
document.bodywhen not in embedded mode or not in a shadow root.
Likely fixes
- In
Modal.vue, resolve the teleport target on mount:- Use
getRootNode()on the component root to detect aShadowRoot. - If in a
ShadowRoot, select#cw-modal-rootthere and use that element. - If not found or not in a shadow root, fall back to
document.body.
- Use
- Remove extra complexity (e.g., hidden anchors or element creation); the modal host is already present in the CE template.
Acceptance criteria
- In embedded mode, the modal stays inside the shadow DOM and is styled (teleport target is the shadow’s
#cw-modal-root). - In normal app mode, behavior remains unchanged (teleport to
body).