vanilla-extract icon indicating copy to clipboard operation
vanilla-extract copied to clipboard

Enable custom injection method for ShadowDom or WebComponents.

Open cpakken opened this issue 3 years ago • 4 comments

Create an option for user to turn off css injection.

plugins: [new VanillaExtractPlugin({inject: false})]

Use Case

I am writing a chrome extension and will be using the shadow dom in order to prevent style clashing when attaching elements. This will apply to WebComponents as well.

Example API

import {getCssText} from '@vanilla-extract/css'; 

// in class
constructor() {
        super();
        this.attachShadow({ mode: 'open' });
        const { shadowRoot } = this;
        container = document.createElement('div');

        styleTag = document.createElement('style');

        //Inject here
        styleTag.innerHTML = getCssText();

        shadowRoot.appendChild(styleTag);            

        shadowRoot.appendChild(container);
        ReactDOM.render(<App />, container);

    }

Inspiration from: https://stackoverflow.com/a/63959654 (Inject CSS styles to shadow root via Webpack)

cpakken avatar Nov 22 '21 00:11 cpakken

It's been a couple of months and wondering if anyone has looked into this.

I've thought of another idea for injecting styles:

import { injectToStyleElement } from '@vanilla-extract/css'; 

// in class
constructor() {
        super();
        this.attachShadow({ mode: 'open' });
        const { shadowRoot } = this;
        const container = document.createElement('div');

        const styleEl = document.createElement('style');

        //Inject here
        injectToStyleElement(styleEl)

        shadowRoot.appendChild(styleEl);            

        shadowRoot.appendChild(container);
        ReactDOM.render(<App />, container);

    }

In the plugin configuration object, we can make an option for manual injection:

{manualInjection: true}

and stop vanilla-extract from creating and inserting its own styleElement into <head />. Then, it will wait for injectToStyleElement(customStyleElement) to be called .

In 'dev/serve' vanilla-extract can update the styles via this function and during a build, we can link with the .css URI.

I'm looking at https://github.com/seek-oss/vanilla-extract/blob/master/packages/css/src/injectStyles.ts#L30-L31 to see where we might implement this feature but I'm not familiar enough with the source yet.

Any feedback regarding this feature or API implementation would be nice

cpakken avatar May 28 '22 04:05 cpakken

I ended up writing a build script to do this. Bit crummy, but works.

// This script inlines the generated style.css into web-components components

const fs = require("fs");
const path = require("path");

const dist = path.resolve(__dirname, "../dist");

const styles = fs.readFileSync(`${dist}/style.css`).toString().trim();

const scriptPath = `${dist}/index.js`;
const scriptContents = fs.readFileSync(scriptPath).toString();
fs.writeFileSync(scriptPath, scriptContents.replace("__styles__", styles));

joshuabaker avatar Jul 20 '22 16:07 joshuabaker

Any news in here? I have a similar problem and I was wondering if its possible to inject the vanilla-extract styles in shadow dom element instead of in the head of the app.

pgonzalez-santiago avatar Oct 20 '22 14:10 pgonzalez-santiago

This feels like something that should be handled outside of Vanilla Extract and documented for each bundler. For example, in webpack you can use the style-loader to inject vanilla extract after all the styles have been extracted into a given shadow DOM. This probably isn't the use case everyone is looking for but this config uses a multi entry point build and webpack layers to build web component friendly islands. https://github.com/mwood23/preact-island-starter

mwood23 avatar Oct 20 '22 16:10 mwood23