whatwg / meta

Discussions and issues without a logical home
Creative Commons Zero v1.0 Universal
93 stars 161 forks source link

Simple HTML (imports) custom components using shadow DOM encapsulation #298

Closed mangelozzi closed 9 months ago

mangelozzi commented 9 months ago

I think declarative custom components is a good step forward, but maybe it can be improved upon...  to me its really not ideal to to repeat the template HTML inards for every instance where it is used, it makes consuming the components much more complicated than simply writing their name. The joy of custom web components is their use.

 I have read the rational, of why it is this way and can appreciate it.

Just a thought, why can't we include the template in the first instance at the top of the page, and every instance thereafter that does not detail a template, uses the previous component that does have a template.

E.g.

<host-element>
    <template shadowroot="open">
        <style>shadow styles</style>
        <h2>Shadow Content</h2>
        <slot></slot>
    </template>
    <h2>Light content 1</h2>
</host-element>

<!-- No template defined use previously defined template -->
<host-element>
    <h2>Light content 2</h2>
</host-element>

However the above idea is not great because it's hard to keep track of which is the first component that has the template. A method that I think will be less error prone is to have a blueprint component at the top of the page, or in the header. One has to have some sort of library of component scripts at the top of the page anyway for all the components using script, something like this: (PS I am not recommending the definition tag, just the concept: where this instance is not instantiated and is not inserted into the DOM for a user to see, but is just a blueprint).

<host-element definition>
    <template shadowroot="open">
        <style>shadow styles</style>
        <h2>Shadow Content</h2>
        <slot></slot>
    </template>
</host-element>
<script>
   ...
</script>

<p>Now we actually use the component</p>
<host-element>
    <h2>Light content Instance</h2>
</host-element>

You may say why not just use imperative components, which is what I do. The downside of this is one has to jump through so many hoops trying to not create a new style sheet (more memory usage) for each custom component instance. And trying to share external stylesheets is not trivial. External stylesheets are re-downloaded for every instance. The hoop is jumpable, using constructable stylesheets with the polyfilling that goes with along it.

I don't want to hi jack this thread so this was moved to: https://github.com/whatwg/dom/issues/new As someone who uses custom elements almost daily, and loves them, in an idea world, we could define the template/styles, and javascript all declaratively, once, and then just use it. Say something like this:

<!-- Pie in the sky dreaming mode activated -->
<!-- my-foo.html is served with a cached header -->
<tagdef name="my-foo" src="static/components/my-foo.html">

<!-- static/components/my-foo.html -->
<style>shadow styles</style>
<link rel="stylesheet" href="static/my-forms.css">
<h2>Shadow Content</h2>
<slot></slot>
<script>
   ...
</script>

Its hard to argue how that is not simply to use and understand compared to what we currently have. Basically what we would love is reusable junks of HTML (which can have styles/javasript), and refer to those encapsulated chunks with a custom tag name. Unfortunately we still don't have a way to import HTML.

annevk commented 9 months ago

I recommend taking this to https://github.com/WICG/webcomponents. I think there's already an issue for this there.