-
Notifications
You must be signed in to change notification settings - Fork 267
Add platform-provided mixins explainer #1208
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
base: main
Are you sure you want to change the base?
Add platform-provided mixins explainer #1208
Conversation
mhochk
left a comment
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.
Looks ready for wider-web discussion to me 👍
dandclark
left a comment
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 promising direction. I like that it addresses the feedback about composability and that it would allow things like <custom-button type=submit> to work.
The main thing that's unclear to me is whether this approach still causes the custom element to sprout attributes and properties associated with the set of supported behaviors when a mixin is added.
I think that's implied but that aspect isn't as clearly laid out as in https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/ElementInternalsType/explainer.md. Could it be stated more explicitly?
anaskim
left a comment
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.
Thanks for the feedback! I added a paragraph in the Platform-Provided Behavior Mixins section to address the exclusion of attributes and properties with mixins in this proposal. Open to changing if I get feedback from web devs saying they would expect them to be included though.
PlatformProvidedMixins/explainer.md
Outdated
| - Event handling: Automatic wiring of platform events (click, keydown, etc.) | ||
| - ARIA defaults: Implicit roles and properties for accessibility. | ||
|
|
||
| Attaching a behavior mixin provides internal platform capabilities but does not automatically add the corresponding properties (like `disabled`, `value`, or `formAction`) or attributes to the custom element. The web component author is responsible for defining these properties and attributes to expose this state to users of the element. |
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.
Not blocking for releasing this explainer, but omitting support for the properties raises some questions about how devs would manually define these in practice.
For example, with an HTMLInputMixin, what would be the way to access the value of the control? The author of the control can expose a value property manually, but where does it get the underlying value to return, or where can it set the control's internal value when the attribute is set? Something like this maybe?
get value() {
// assert: this.internals_.mixins[0] is a HTMLInputMixin
return this.internals_.mixins[0].value;
}
set value(value) {
// assert: this.internals_.mixins[0] is a HTMLInputMixin
return this.internals_.mixins[0].value = value;
}Would this also be the way that methods like checkValidity() would be used?
class MyCustomInput extends HTMLElement {
checkValidity() {
// assert: this.internals_.mixins[0] is a HTMLInpuMixin
return this.internals_.mixins[0].checkValidity();
}
}And maybe disabled would be set this way too?
class MyCustomButton extends HTMLElement {
set disabled(isDisabled) {
// assert: this.internals_.mixins[0] is a HTMLButtonMixin
this.internals_.mixins[0].disabled = isDisabled;
}
}If there isn't a way to get at the "real" value of these properties then it seems like devs will still have to do significant work to reimplement a lot of this functionality.
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.
Although I guess it couldn't work exactly this way, since this.internals_.mixins contains (I think) global/static HTMLInputMixin/HTMLButtonMixin etc objects, not an object associated with the specific instance of the control. So might need to invent a way to get to the internal versions of these attributes/properties/methods associated with the specific control instance. The old type proposal did this by having internals sprout another interface associated with the control instance: https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/ElementInternalsType/explainer.md#example-1
PlatformProvidedMixins/explainer.md
Outdated
| ```javascript | ||
| class MyCustomInput extends HTMLElement { | ||
| get value() { | ||
| return this._internals.getMixinState(HTMLInputMixin).value; |
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.
An alternative structure that could me more ergonomic would be to give ElementInternals properties for HTMLInputMixinState, etc, that would be non-null only if that mixin is passed to attachInternals. Then the example would look like:
class MyCustomInput extends HTMLElement {
get value() {
return this._internals.htmlInputMixinState.value;
}
checkValidity() {
return this._internals.htmlInputMixinState.checkValidity();
}
}I observe though that this is kind of converging back towards the type proposal. Other than the use of the word "mixin", I guess the key differences are:
- Applying the behaviors happens at
attachInternalstime, not statically, so different component instances can have different behaviors based on attributes or other state. - This new syntax allows for composition by taking an array of behaviors instead of a single type string.
Are these differences enough to meet the objections that "type" ran into?
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.
Yeah looks this close to an iteration of the .type proposal. I'm loosely basing this new one on this comment by Rob Eisenberg WICG/webcomponents#814 (comment). My general reading of the objections has been that the ElementInternals.type proposal had: "Magic" inheritance and too many vague/confusing things bundled together, in addition to some people not liking the static syntax. That's why I initially wanted to keep it as straight forward as possible and make the mixin very straightforward. I think the composition part is definitely a good point, but I wonder if we're going to get pushback for using ElementInternals instead of static class mixins (alternative 1 in the explainer).
V1 includes:
attachInternals()and avoid dynamic changes at runtime.ElementInternalsto query behaviors.