Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Font & assets load issue when append styles in shadow DOM #213

Open
subramanian-iouring opened this issue Dec 16, 2024 · 4 comments
Open

Comments

@subramanian-iouring
Copy link

subramanian-iouring commented Dec 16, 2024

import styles from "./Style.json";

const AppWrapper = (props: any) => {

    const { children } = props;

    const [
        domRef, setDomRef
    ] = useState<HTMLStyleElement>();

    const cache = useMemo(() => {
        if (domRef)
            return createCache({ key: "css", prepend: true, container: domRef });
        return null;
    }, [
        domRef
    ]);

    const getRef = useCallback((ref: HTMLStyleElement | null) => {
        if (ref)
            setDomRef(ref);
    }, [
    ]);

    return <StyledEngineProvider injectFirst>
        <Provider store={store}>
            <style ref={getRef}></style>
            <style>{styles}</style>  // style injection

            {cache !== null ? <CacheProvider value={cache}> {children} </CacheProvider> : null}
        </Provider>
    </StyledEngineProvider>;
};

const MyComponentWebComponent = r2wc(AppWrapper, {
    shadow: "open",
    props: {
        payload: "string",
        eventcallback: "function"
    }
});

customElements.define("web-app", MyComponentWebComponent);

In above code, we are injecting css styles by <style>{styles}</style> tag.

But the fonts, assets and color variables [:root { --white: #ffffff; }] are not applicable when we build and use this custom element in another app.

Note: Style.json contains raw css.
":root{--primary-color:#2ea7e0;--primary-border:#2ea7e073;}
.logo-container .app-logo{color:var(--primary-color)}.logo-container.empty-container .app-logo{height:50px;opacity:.2}"

@subramanian-iouring
Copy link
Author

subramanian-iouring commented Dec 16, 2024

import styles from "./Style.json";

const MyComponentWebComponent = r2wc(AppContainer, {
    shadow: "open",
    props: {
        payload: "string",
        eventcallback: "function"
    }
});

class MyComponentElement extends MyComponentWebComponent {
    constructor() {
        super();
  
        // Inject styles into the shadow DOM

        // Method 1
        // const shadow: any = this.shadowRoot;
        // const style = document.createElement("style");
        // style.textContent = styles;
        // shadow.appendChild(style);

        // Method 2        
        // const sheet = new CSSStyleSheet();
        // sheet.replaceSync(styles);
        // shadow.adoptedStyleSheets = [
        //     sheet
        // ];

        // Method 3
        // const link = document.createElement("link");
        // link.setAttribute("rel", "stylesheet");
        // link.setAttribute("href", "https://domain.com/path/to/static/css/file/file-name.css");
        // shadow.appendChild(link);
    }
}

customElements.define("nxt-option", MyComponentElement);

I have tried these methods to inject css, same issue occur. styles are append and working. CSS variables are not append in dom and fonts are not even downloaded in browser.

@bmomberger-bitovi
Copy link
Contributor

Instead of :root{--primary-color:#2ea7e0;--primary-border:#2ea7e073;}
try doing
:host{--primary-color:#2ea7e0;--primary-border:#2ea7e073;}

:host() has no effect outside of shadow DOM, and :root() has no effect inside, so you could build your CSS files to be reusable in light and shadow DOM components by duplicating the variable declarations within the :root and :host blocks.

@subramanian-iouring
Copy link
Author

subramanian-iouring commented Dec 17, 2024

Instead of :root{--primary-color:#2ea7e0;--primary-border:#2ea7e073;} try doing :host{--primary-color:#2ea7e0;--primary-border:#2ea7e073;}

:host() has no effect outside of shadow DOM, and :root() has no effect inside, so you could build your CSS files to be reusable in light and shadow DOM components by duplicating the variable declarations within the :root and :host blocks.

@bmomberger-bitovi Thanks for quick reply.
here am using theme based app, so i have 2 files like below, dark theme is default.

_colors-dark.scss
:root{--primary-color:#2ea7e0;--primary-border:#2ea7e073;}

_colors-light.scss
[data-theme="light"] {--primary-color:#FFFFFF;--primary-border:#404040;}

when i change "root" as "host" it's working fine. how can i get this theme setup?

@bmomberger-bitovi
Copy link
Contributor

Load both the changed colors-dark and the colors-light stylesheets into the shadow DOM using any of the three methods that you outlined above. However, to successfully change the theme, you will need to set a root element inside the Shadow DOM to have data-theme="light". It will not respond to the attribute being set on elements in the Light DOM, even if they are ancestors of the custom element containing your component.

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

No branches or pull requests

2 participants