-
Notifications
You must be signed in to change notification settings - Fork 266
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
|
|
||
| **Pros:** | ||
| - Familiar JavaScript pattern. | ||
| - Prototype-based composition. |
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.
Another pro to this approach is that it allows for child classes to easily extend from mixins. e.g.
class CustomSubmitButton extends HTMLSubmitButtonMixin(HTMLElement) { ... }
class ExtraCustomSubmitButton extends CustomSubmitButton {...}
Is this possible with the current mixin proposal?
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.
Yes, we talked about in the meeting about child classes inheriting ElementInternals. I tested it and child classes do inherit the instance and can modify it. With the proposed approach we could have:
class ParentElement extends HTMLElement {
#internals;
constructor() {
super();
this.#internals = this.attachInternals();
// ...
this._internals = this.attachInternals({ mixins });
}
_getInternals() {
return this.#internals;
}
}
class ChildElement extends ParentElement {
constructor() {
super();
const internals = this._getInternals();
internals.role = 'checkbox';
const isSubmit = this._internals.mixins.includes(HTMLSubmitButtonMixin);
if (isSubmit) {
// ...
}
}
}| **Cons:** | ||
| - Doesn't currently address form submission behavior. | ||
| - Scoped to specific attributes rather than general behaviors. | ||
|
|
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.
Does it make sense to list "Extend Markup Like Customizable Select"? Or is that too different of a problem? The dealbreaking con with this approach is that it won't work for all types (or any types beyond select?).
https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select
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.
Yes, added it as an alternative. PTAL.
| name: Platform-provided mixins | ||
| about: new issue | ||
| title: "[Platform-provided mixins] <TITLE 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.
NIT: The name/title is typically Title Cased
| name: Platform-provided mixins | |
| about: new issue | |
| title: "[Platform-provided mixins] <TITLE HERE>" | |
| name: Platform-Provided Mixins | |
| about: new issue | |
| title: "[Platform-Provided Mixins] <TITLE HERE>" |
| Custom element authors can't access platform behaviors that are built into native HTML elements. This forces them to either: | ||
|
|
||
| 1. Use customized built-ins (`is/extends` syntax), which have [Shadow DOM limitations](https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#elements_you_can_attach_a_shadow_to) and [can't use the ElementInternals API](https://github.com/whatwg/html/issues/5166). | ||
| 2. Try to reimplement platform logic in JavaScript, which is error-prone. |
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.
Might be worth tossing in that it would also be less performant and 100% broken if JavaScript is disabled.
| This proposal is informed by: | ||
|
|
||
| 1. Issue discussions spanning multiple years: | ||
| - [WICG/webcomponents#814](https://github.com/WICG/webcomponents/issues/814) - Form submission from custom elements (400+ comments) |
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.
NIT: This looks to only have ~50 direct comments. I'm guessing you're including all the comments from all the other Issues that link to this Issue as well?
I recommend just not including the call-out about how many comments it has, as it seems to imply that this single Issue covers a drastically larger discussion than the others.
| - [WICG/webcomponents#814](https://github.com/WICG/webcomponents/issues/814) - Form submission from custom elements (400+ comments) | |
| - [WICG/webcomponents#814](https://github.com/WICG/webcomponents/issues/814) - Form submission from custom elements |
| - `ElementInternals` instances expose a read-only `mixins` property returning the list of attached behaviors. | ||
| - Supports composition as web authors can pass many behaviors. | ||
|
|
||
| *Note: The API uses the term "mixins" instead of "behaviors" to avoid potential confusion with the spelling of "behavior" vs "behaviour".* |
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 don't think using "behaviors" would be a problem on account of spelling. The web standards space has already aligned on "behaviors" being the spelling for things like scroll-behavior and overscroll-behavior, similar to its use of "color" throughout (rather than "colour").
| - While this proposal focuses on an imperative API, the underlying model of attaching mixins via `ElementInternals` is compatible with future declarative APIs. | ||
| - A child class extends the parent's functionality and retains access to the `ElementInternals` object and its active mixins, allowing for standard object-oriented extension patterns. | ||
|
|
||
| ### Use case: Design System Button |
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.
To complete the picture of what this approach would look like as a framework, I recommend adding an additional example that shows what inheritance and multiple-mixins would look like. Preface it with a disclaimer that the initial proposal is only for a single mixin, but that this is what the future might look like.
In particular, I think it will be worthwhile to show:
- How a parent class and sub-class can both contribute to what mixins get applied (since
attachInternalsmay only be called once, I believe it would require custom coordination) - How a class can determine what mixins are "winning" when the mixins array has multiple values (since just doing an
includescheck won't tell you what aspects of that mixin are being overriden by another mixin)
A possible scenario for this could be a class that wants HTMLSubmitButtonMixin, and then a sub-class that wants to retain the :default/enter behaviors of that (as well as the custom html/style), but wants to also add HTMLResetButtonMixin to reset the form instead of submitting it.
| - Solves specific use cases like popovers and drag-and-drop. | ||
| - Hides implementation details from the consumer. | ||
|
|
||
| **Cons:** |
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.
Another con would be that since the composition doesn't have an order/sequence to it, the web developer would not be able to specify a desired "winner" when using multiple behaviors that happen to impact a shared value or scenario.
V1 includes:
attachInternals()and avoid dynamic changes at runtime.ElementInternalsto query behaviors.