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

Shadow DOM only #19

Closed
lbineau opened this issue May 21, 2024 · 13 comments
Closed

Shadow DOM only #19

lbineau opened this issue May 21, 2024 · 13 comments

Comments

@lbineau
Copy link

lbineau commented May 21, 2024

Hello @EranGrin,

Thank you for creating this library. I think the main issue with Vue 3 WebComponents is their lack of support for normal DOM and just support of shadow DOM. It creates some issues with styling scopes, ex: not possible to use an external CSS stylesheet.
Does your library support both?

Best regards.

@lbineau lbineau changed the title Shadow DOM Shadow DOM only May 21, 2024
@EranGrin
Copy link
Owner

Hi There,
This isn't the first time I've come across this question, but I'm always curious, considering shadowDOM is one of the main features of web component encapsulation.
With that being said, I can add this feature, but it does feel like it's missing the entire point of web component usage.

I would be glad if someone could convince me otherwise

@lbineau
Copy link
Author

lbineau commented May 21, 2024

Hello @EranGrin,

Thanks for replying so fast.
It is an issue that I'm not the only one to have in my research: vuejs/core#4314 (comment) / vuejs/core#4404

So basically we use Vue in a monolith website. Most of the HTML is rendered by the backend and we use Vue to enhance the interactivity of the website.
The main issue is Vue always needs a root node for building an application. The workaround is to encapsulate the component as a WebComponent.
We have a common styling for the whole company (i.e. a CSS stylesheet coming through a CDN)
Imagine you have a .button definition in this stylesheet, you cannot share the definition of a <button> between a Vue component and the static content as the styles are isolated due to shadowDOM.

@EranGrin
Copy link
Owner

I had a look at the vue core code, it might be possible to override the attach shadow dom, but I'm not sure what will be the entire implications.
I can work on this next week, till then I'm on holiday

@lbineau
Copy link
Author

lbineau commented May 21, 2024

The main issue I've read so far is the impossibility of using slot because it is part of the shadowDOM API.
That I would need to have in my use-case unfortunately...

@EranGrin
Copy link
Owner

I am not sure if you are aware of this, but CSS custom properties (variables) can penetrate the Shadow DOM

@lbineau
Copy link
Author

lbineau commented May 22, 2024

Yes I know, I'm refering to global CSS. The goal being not to have to rewrite all styles for the default button / headings / etc.
But maybe I'm taking the problem the wrong way.

@EranGrin
Copy link
Owner

@lbineau good news. I found a way to resolve the problem. It might take me a few days more to pack it and make some clean-ups. I spent a lot of time on this today, and I have to do some work that makes money as well.
The main issue was with the slots, as you mentioned before, this was painful to solve

@haydenbbickerton
Copy link

@EranGrin Fantastic! What was the fix for you? Just a general description of it would be great

@EranGrin
Copy link
Owner

EranGrin commented Jun 3, 2024

New Release 1.5.0 is live 🔥
Here is the demo of web component without shadow dom
https://stackblitz.com/~/github.com/EranGrin/web-component-no-shadow-dom-demo

@firescript
Copy link

firescript commented Jun 3, 2024

First of all nice work @EranGrin, I checked your demo very cool! Would your Shadow Dom logic apply to this PR? vuejs/core#4404 - that would be a big win for the "reactivity sprinkling" use case that @lbineau described.

I admit I am in scenario where I'm building a Wordpress Theme and want to inject vue logic for certain e-commerce scenarios, and have had to create a process to bundle "web component" styles and import that specific stylesheet into the <style> of each vue component i use as a web component. This does lead to tailwind base classes being duplicated across all my shadow doms, it works, its just i'm adding about 50kb of inline css for each shadow dom I add, just to leverage tailwind. Being able to just use the main css file that the page as a whole uses would be ideal.

@EranGrin
Copy link
Owner

EranGrin commented Jun 4, 2024

Hi @firescript,

I have doubt if vue core team will ever accept this PR as it's adding this strange path html-parsed-element.ts instead of the HTMLElement for the base class,
We can work on another PR which introduces this feature in a more appropriate way, but there are several use-cases such as SSR and hydration which also part of the web component core api,
However, this may take time for me to do it alone, as I don't really need it, and I'm quite busy.

Regarding your use case, you could also use the wrapper as is without shadow Dom.
If you wrap all the components with the plugin, you will also be able to solve your problem.

@lbineau
Copy link
Author

lbineau commented Jun 12, 2024

New Release 1.5.0 is live 🔥 Here is the demo of web component without shadow dom https://stackblitz.com/~/github.com/EranGrin/web-component-no-shadow-dom-demo

Thanks a lot for working on that topic, that's great news! I'll test it locally because the stackblitz link is failing to install error An unexpected error occurred: "too much recursion"..
In the meantime, I've worked on a different approach by initializing Vue App inside a customElements.

customElements.define('vue-app', class extends HTMLElement {
    app;
    constructor() {
	super();
        if (this.dataset.vApp !== undefined) return
        this.app = createApp(App})
    }
    connectedCallback () {
        // Use in DOM root component template
        // https://vuejs.org/guide/essentials/application.html#in-dom-root-component-template
        this.app.mount(this)
    }
    disconnectedCallback () {
        this.app.unmount()
        this.app = null
    }
})

The approach is very naive but at least it worked in my case.
I'm closing the issue because you implemented the solution.

@lbineau lbineau closed this as completed Jun 12, 2024
@EranGrin
Copy link
Owner

@firescript
I add support to the SFC with nested component style and shadowDOM option, you can check the latest release

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

4 participants