Skip to content

Component-patterns with web-components (v4) #8690

@KenAJoh

Description

@KenAJoh

Describe the problem

The new changes made to custom-elements 🎉 changed how get_current_component works, and with it comes some changes to how one create a component-api with purely web-components. (as far as my current testing has lead me to believe, but might be mistaken here)

A constant hassle when working with shadow dom is how one passes values between the shadow-dom, and in v3 this could be "solved" by using get_current_component().shadowRoot to access both parent and childrens within slots. This allowed the following component-pattern:

<wc-accordion>     // <- shadowroot open
    <wc-accordion-item>   //  <- shadowroot open
        <wc-accordion-heading>   // <- shadowroot open
			Heading text
        </wc-accordion-heading>    
        <wc-accordion-content>   // <- shadowroot open
			Content text
        </wc-accordion-content>
    </wc-accordion-item>
</wc-accordion>

where accordion-item stored and passed both the "open"-state and the "ontoggle"-handler down to accordion-heading and accordion-content. This "worked", but was not pain-free...

One could sort-of solve this now by using the following pattern:

<wc-accordion>
    <wc-accordion-item heading="heading-text">
			content
    </wc-accordion-item>
</wc-accordion>
// or
<wc-accordion>
    <wc-accordion-item >
           <span slotname="heading">heading</span>
           <div slotname="content">content</div>
    </wc-accordion-item>
</wc-accordion>

But that doesn't solve the core issue...

One could dispatch events from accordion-header up to item, following the 'properties down, events up'-pattern, but what is the expected and preferred way to pass the open-prop down across the nested shadow-dom?
This closed issue adds context-support for web-components, possibly solving this. But so far with 4.0.0-next.0 i have yet to get this working (can set context, but getContext is always undefined)

What i'm getting to is: How does Sveltes custom-elements want and expect a good component-pattern to look and work with 2-way communication between components?

Describe the proposed solution

Stencil solves this by making it possible to get and change child web-components with querySelector directly on the parent element even its if its nested shadow-doms

this.accordionHeader = this.el.querySelector("wc-accordion-header");
this.accordionHeader.open = this.open;

How this is implemented i'm not aware of, and might only be possible with virtual-dom (as stencil uses)

Lit solves this with giving access to this.children or this.defaultNodes (not 100% on defaultNodes, but thats how spectrum web-components does it)

Alternatives considered

In v4 one could disable shadow-dom for the nested elements, and only use shadow-dom on the wrapper. This could a viable pattern, but have yet to do any testing with it for now. accordion-item will still be outside the wrappers shadow-dom, so not viable.

The easiest way i have found for now is to make queries on the document, but this adds a different complexity with checking for the correct dom-element and adding unique identifiers to each component instance.

This issue under the 4.x milestone is related and would solve this to a certain degree. Found a PR on this, but its 3y old now..

Importance

would make my life easier

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions