diff --git a/packages/odyssey-react-mui/src/ui-shell/UiShell.test.tsx b/packages/odyssey-react-mui/src/ui-shell/UiShell.test.tsx index 639117d33..63d49a8e3 100644 --- a/packages/odyssey-react-mui/src/ui-shell/UiShell.test.tsx +++ b/packages/odyssey-react-mui/src/ui-shell/UiShell.test.tsx @@ -197,8 +197,8 @@ describe("UiShell", () => { } appRootElement={document.createElement("div")} - emotionRootElement={document.createElement("div")} onSubscriptionCreated={() => {}} + stylesRootElement={document.createElement("div")} subscribeToPropChanges={subscribeToPropChanges} />, ); @@ -228,8 +228,8 @@ describe("UiShell", () => { } appRootElement={document.createElement("div")} - emotionRootElement={document.createElement("div")} onSubscriptionCreated={() => {}} + stylesRootElement={document.createElement("div")} subscribeToPropChanges={subscribeToPropChanges} />, ); diff --git a/packages/odyssey-react-mui/src/ui-shell/UiShell.tsx b/packages/odyssey-react-mui/src/ui-shell/UiShell.tsx index 4c6a8067b..d25f7af6f 100644 --- a/packages/odyssey-react-mui/src/ui-shell/UiShell.tsx +++ b/packages/odyssey-react-mui/src/ui-shell/UiShell.tsx @@ -22,7 +22,7 @@ import { ErrorBoundary, ErrorBoundaryProps } from "react-error-boundary"; import { SideNav, type SideNavProps } from "../labs/SideNav"; import { TopNav, type TopNavProps } from "../labs/TopNav"; import { OdysseyProvider } from "../OdysseyProvider"; -import { ShadowDomElements } from "../web-component/shadow-dom"; +import { type ReactRootElements } from "../web-component"; const appContainerStyles = { flexGrow: "1", @@ -79,7 +79,7 @@ export type UiShellProps = { subscribeToPropChanges: ( subscriber: (componentProps: SetStateAction) => void, ) => () => void; -} & ShadowDomElements; +} & ReactRootElements; /** * Our new Unified Platform UI Shell. @@ -91,10 +91,10 @@ export type UiShellProps = { const UiShell = ({ appComponent, appRootElement, - emotionRootElement, onError = console.error, onSubscriptionCreated, optionalComponents, + stylesRootElement, subscribeToPropChanges, }: UiShellProps) => { const [componentProps, setComponentProps] = useState(defaultComponentProps); @@ -115,7 +115,7 @@ const UiShell = ({ return (
diff --git a/packages/odyssey-react-mui/src/ui-shell/renderUiShell.tsx b/packages/odyssey-react-mui/src/ui-shell/renderUiShell.tsx index 2bc8e9e74..72a997278 100644 --- a/packages/odyssey-react-mui/src/ui-shell/renderUiShell.tsx +++ b/packages/odyssey-react-mui/src/ui-shell/renderUiShell.tsx @@ -95,7 +95,6 @@ export const renderUiShell = ({ } appRootElement={shadowDomElements.appRootElement} - emotionRootElement={shadowDomElements.emotionRootElement} onError={onError} onSubscriptionCreated={publishSubscriptionCreated} optionalComponents={Object.fromEntries( @@ -106,6 +105,7 @@ export const renderUiShell = ({ ], ), )} + stylesRootElement={shadowDomElements.stylesRootElement} subscribeToPropChanges={subscribeToPropChanges} /> diff --git a/packages/odyssey-react-mui/src/web-component/renderReactInWebComponent.test.tsx b/packages/odyssey-react-mui/src/web-component/renderReactInWebComponent.test.tsx index c160c6ffa..23b612c33 100644 --- a/packages/odyssey-react-mui/src/web-component/renderReactInWebComponent.test.tsx +++ b/packages/odyssey-react-mui/src/web-component/renderReactInWebComponent.test.tsx @@ -13,11 +13,39 @@ import { waitFor } from "@testing-library/dom"; import { - ReactInWebComponentElement, + createReactRootElements, reactWebComponentElementName, renderReactInWebComponent, + type ReactInWebComponentElement, } from "./renderReactInWebComponent"; +describe("createReactRootElements", () => { + test("returns two elements at attach to a Shadow DOM", () => { + const { appRootElement, stylesRootElement } = createReactRootElements(); + + expect(appRootElement).toBeInstanceOf(HTMLDivElement); + expect(stylesRootElement).toBeInstanceOf(HTMLDivElement); + }); + + test("App root element has the correct attributes", () => { + const { appRootElement } = createReactRootElements(); + + expect(appRootElement).toHaveAttribute("id", "app-root"); + expect(appRootElement).toHaveAttribute("style", "height: inherit;"); + }); + + test("Emotion root element has the correct attributes", () => { + const nonce = "hello-world"; + + window.cspNonce = nonce; + + const { stylesRootElement } = createReactRootElements(); + + expect(stylesRootElement).toHaveAttribute("id", "style-root"); + expect(stylesRootElement).toHaveAttribute("nonce", nonce); + }); +}); + describe("renderReactInWebComponent", () => { afterEach(() => { // Remove any appended elements diff --git a/packages/odyssey-react-mui/src/web-component/renderReactInWebComponent.ts b/packages/odyssey-react-mui/src/web-component/renderReactInWebComponent.ts index d699ca9bc..a57532b73 100644 --- a/packages/odyssey-react-mui/src/web-component/renderReactInWebComponent.ts +++ b/packages/odyssey-react-mui/src/web-component/renderReactInWebComponent.ts @@ -13,27 +13,57 @@ import { type ReactNode } from "react"; import { createRoot, type Root } from "react-dom/client"; -import { - createUnattachedShadowDomElements, - type ShadowDomElements, -} from "./shadow-dom"; +/** + * Creates elements for a Shadow DOM that Odyssey will render into. + * The Emotion root is for `