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

[Declarative Shadow DOM Style Sharing] Is DSD the right primitive for reusing component templates? #885

Open
dgp1130 opened this issue Oct 5, 2024 · 1 comment

Comments

@dgp1130
Copy link

dgp1130 commented Oct 5, 2024

The proposal describes a mechanism for repeating a template across multiple elements in the documents. Reproducing the relevant example below:

<template type="module" specifier="/foo.html"> 
<!-- This template defines an HTML module whose contents are given by the markup 
     placed here, inserted into the module map with the specifier "/foo.html" --> 
... 
</template> 
<my-element> 
  <!-- The `shadoowroothtml` attribute causes the `<template>` to populate the shadow root by 
cloning the contents of the HTML module given by the "/foo.html" specifier, instead of 
parsing HTML inside the <template>. --> 
  <template shadowrootmode="open" shadowrootadoptedstylesheets="/foo.css" shadowroothtml="/foo.html"></template> 
</my-element>

I'm on board with the general idea here, but this couples the use case of repeating a template with shadow DOM in a way which I'm not convinced is desirable.

First, all users of this must use shadow DOM, which has implications on how styles are authored and linked into the document. Many users may want to repeat a single HTML template without pulling on the baggage of shadow DOM.

Second, I assume slots would still be supported for each usage of a repeated template. That makes a certain amount of sense that static, reusable parts of an element could be shared in a single template while the dynamic pieces can be slotted in via the light DOM like so:

<template type="module" specifier="/foo.html"> 
  <div>Hello, <slot name="username"></slot>! Or would you prefer <slot name="firstname"></slot>?</div>
</template>

<my-element> 
  <template shadowrootmode="open" shadowroothtml="/foo.html"></template>
  <span slot="username">develwithoutacause</span>
  <span slot="firstname">Doug</span>
</my-element>

While this static / dynamic separation is useful, it is inherently coupled to the private / public separation of shadow and light DOM. If I want firstname to be public and replaceable by consumers of my-element, that's fine. But if I want username to be private and kept constant from the initial render, then I can't reuse a single static template. Otherwise any consumer of my-element could replace the <span slot="username"> which exists in the light DOM, and I have no way to protect this implementation detail.

I don't have a great solution to this (private slots, parameterized templates?) but this leads me to believe that we have two distinct problems:

  1. Public vs private DOM
  2. Dynamic vs static DOM

We have one mechanism in light vs shadow DOM, and solving both problems with that same mechanism inherently couples them together in an undesirable way. This leads me to believe that shadow DOM is not the right primitive for building a repeatable template system and we may want some other abstraction.

(Slightly off-topic: Given that HTML modules is not quite a thing yet, I suspect it would be better to decouple this proposal from that entirely and just focus on reusing styles, dropping shadowroothtml completely. I definitely have hesitations about adopting anything in that space without stronger signals for HTML modules on their own, but I'm not super involved with web standards, so I'm not an expert on how these proposals actually move through the process.)

@justinfagnani
Copy link

Declarative shadow DOM is not about reuse in any kind of way. It's only about serializing the contents of a ShadowRoot.

I do think the explainer is a bit off in the HTML. To me <template type="module" specifier="/foo.html"> would be a serialization of an HTML module. An HTML modules might contain a template that's meant to be stamped out, but the HTML module itself wouldn't be the template meant to be stamped out.

And even if the HTML module did contain a <template> for use by component, it most likely couldn't be used as-is without either a templating library to process it and implement bindings/interpolations, or a full declarative template system in HTML like Template Instantiation.

I personally would rather see shadowroothtml removed from the explainer because I do think it confuses two use cases: bundling HTML modules and template instantiation.

Also, this is another reason I think using <script> for all inlined modules is semantically more correct. We're really talking about two features here: 1) a feature to inline part of the module graph into HTML, and 2) a feature to reference CSS modules from the module graph into declarative shadow roots. I feel like (1) should be done consistently in a way that works for any current and future module type.

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