-
Notifications
You must be signed in to change notification settings - Fork 376
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
[Scoped registry] Clarify relationship with shadow roots #965
base: gh-pages
Are you sure you want to change the base?
Conversation
After reading through this proposal, I was a bit confused about the relationship between shadow roots and custom elements. It took me a moment to realize that custom elements' definitions are not defined by the shadow root _attached_ to them, but instead to the shadow root that _contains_ them. This PR adds some clarifying notes that hopefully would help others reading this document. (Assuming that my interpretation is correct. 🙂)
</body> | ||
``` | ||
|
||
In the above example, `<light-element>` is scoped within the shadow root of its containing `<shadow-element>`, whereas `<shadow-element>` is defined at the global document level. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we reflect that scope could be more flexible and tied not just to shadowRoot?
There is a scenario when light-element
would have declarative custom element definition inside which would be logical to scope to the parent (or somehow named scope) instead whole page.
<body>
<light-element>
#light-root (registry=myCustomRegistry)
<definition tag="custom-element">...</definition><!-- syntax is not clear as of now -->
<custom-element>
<div>Light DOM</div>
</custom-element>
</light-element>
</body>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand this. Declarative custom element definitions do not exist yet, and there's no such thing as a light-root.
If <light-element>
wants its own scope it'll have to programmatically create one and ensure that an elements it create use scoped instantiation APIs, which right now are only available on ShadowRoot, though we could conceivably also add them to CustomElementRegistry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was under the impression that Declarative Shadow DOM was out-of-scope for this proposal... Although there is some reference to it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Declarative Shadow DOM has its sibling and evolution as Declarative Custom Element which could use shadow but also could live without, both in a baking now, not yet a proposal but already have POCs. Both could have a use for scoped registry as scoped by encapsulation as by namespace( a components library ).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Declarative shadow DOM has nothing to do with declarative custom elements. They are unrelated conceptually, as declarative custom elements would not use declarative shadow DOM, and are at very, very different stages of proposal and implementation.
@@ -60,6 +60,8 @@ registry.define('other-element', OtherElement); | |||
|
|||
Definitions in this registry do not apply to the main document, and vice-versa. The registry must contain definitions for all elements used. | |||
|
|||
Note that, in the above example, `<other-element>` is defined in the scoped registry, not `<my-element>`. The registry applies to definitions _within_ the shadow root, not the element that the shadow root is attached to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm finding this wording a bit unclear.... especially "<other-element>
is defined in the scoped registry, not <my-element>
" and "not the element that the shadow root is attached to."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to tweak the language a bit. Maybe I'm only muddying things further, but the existence of <my-element>
really confused me when I first read this, so I'm trying to call that out.
Arguably this example could just attach the shadow root to a div (or something), but that might be even more confusing since it isn't a common usage of shadow DOM.
@@ -119,6 +121,23 @@ As a result, it must limit constructors by default to only looking up registrati | |||
|
|||
This poses a limitation for authors trying to use the constructor to create new elements associated to scoped registries but not registered as global. More flexibility can be analyzed post MVP, for now, a user-land abstraction can help by keeping track of the constructor and its respective registry. | |||
|
|||
### Note on light DOM custom elements | |||
|
|||
Custom elements that use light DOM (i.e. that don't call `this.attachShadow()`) may be scoped, but they must be scoped within a shadow root. For example: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a bit confusing as there's no difference in defining elements in a scoped registry, regardless of whether they do or don't use shadow DOM. This seems to be blurring the language between what scope an element is defined in vs whether the element can have its own scope for its own definitions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this section to answer a question that may pop into people's heads (it certainly popped into mine), which is: "Wait, this proposal doesn't work for light-DOM-using web components?"
I'm trying to demonstrate that light-DOM-using components are perfectly compatible with this proposal, although maybe there's a better way to phrase this.
</body> | ||
``` | ||
|
||
In the above example, `<light-element>` is scoped within the shadow root of its containing `<shadow-element>`, whereas `<shadow-element>` is defined at the global document level. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand this. Declarative custom element definitions do not exist yet, and there's no such thing as a light-root.
If <light-element>
wants its own scope it'll have to programmatically create one and ensure that an elements it create use scoped instantiation APIs, which right now are only available on ShadowRoot, though we could conceivably also add them to CustomElementRegistry.
@nolanlawson Sorry, I'm a little confused by your confusion and the statement "custom elements' definitions are not defined by the shadow root attached to them, but instead to the shadow root that contains them". In this proposal ShadowRoots can be associated with a registry. When they are, elements created in that ShadowRoot via the scoped element creation APIs ( |
Thanks @justinfagnani yes, I think I get that subtlety now. My confusion stems from the fact that in this case: const registry = new CustomElementRegistry()
customElements.define('my-element', class extends HTMLElement {
constructor() {
super()
this.attachShadow({ mode: 'open', registry })
}
}) ... I could be wrong, but it seems to me that this could be a common confusion, because of the proximity of |
After reading through this proposal, I was a bit confused about the relationship between shadow roots and custom elements. It took me a moment to realize that custom elements' definitions are not defined by the shadow root attached to them, but instead to the shadow root that contains them.
This PR adds some clarifying notes that hopefully would help others reading this document. (Assuming that my interpretation is correct. 🙂)