Re: [w3c/webcomponents] The is="" attribute is confusing? Maybe we should encourage only ES6 class-based extension. (#509)

@WebReflection 

> `<button is="my-button">` **and** `<button is="my-better-button">`

That makes sense, but someone else might do it the wrong way that I pointed out. In order to have a consistent API, `<my-better-button is="my-button">` should also work (although it doesn't fallback). The `my-better-button` and `my-button` in `<my-better-button is="my-button">` should be able to be built-in names or custom element names just the same.

> While you'd use `{extends: 'button'}` for the first case, you'll use `{extends: 'my-button'}` in the second because being inherited via `MyBetterButton` it needs to be known.

This is where I lean on what @oleersoy is saying: that the 3rd argument should not be required (one of the original points of my OP).

Also, without the 3rd argument, that whole `customElements.whenDefined` hack won't be required. That is really ugly because now imagine how Custom Element authors are going to write ES6 modules to define elements that extends other elements. The module author will have to export a promise, and anyone who imports a class from that module will have to await a promise. I don't think that is ideal, it adds a new level of complexity compared to synchronously exporting a class definition and then importing it synchronously in another module.

So, if the `is=""` attribute API is something that we would keep, I would argue these points:

1. No 3rd argument to `customElement.define` should be required, so just `customElements.define('fancy-button', FancyButton);`, not `customElements.define('fancy-button', FancyButton, {extends: 'button'});`.
2. Modify the spec to require all built-in elements to match one-to-one with built-in classes. We will need a base class with common functionality for quote-like elements in true object-oriented fashion, then `HTMLQElement`, `HTMLCiteElement`, and `HTMLBlockquoteElement` for the specific element classes. This automatically eliminated the need for the ugly `{extends:}` argument.
3. `<button is="my-button">` **and** `<button is="my-better-button">` is the recommended way to use PE where in that example the class associated with `my-better-button` extends from that class associated with `my-button`, via JavaScript inheritance without the `{extends:}` argument.
4. <my-better-button is="my-button">` should still work. When `my-button` is not available, `my-better-button` should be used, even if `my-button` does not extend `my-better-button`.
5. The argument to the `is=""` attribute is not required to extend the element owning the `is=""` attribute, and in no way should the `is=""` attribute signify that the specified element extends the owner element. For example, in `<some-element is="unrelated-element">`, when the definition for `unrelated-element` exists, then the element is instantiated (upgraded) as an instance of the class associated with `unrelated-element` with whatever prototype inheritance it happens to have, which may not include the prototype associated with `some-element`. If the definition for `unrelated-element` does not exist but the definition for `some-element` does, then the element is instantiated (upgraded) as an instance of the class associated with `some-element`, which may have a prototype chain that is completely unrelated to the prototype chain of the class associated with `unrelated-element`.

If the API is like that, it will be more DRY, and it will be more useful specifically for people who want any form of progressive enhancement of built-in elements or custom elements alike. At that point, any argument against the API is really an argument against progressive enhancement IMO, not an argument relating to the confusion that happens due to the fact that currently the API is limited to use with built-in elements and, not an argument relating to the fact that both `is=""` and `{extends:}` are required, and not an argument relating to possible confusion from `is=""` being used to define inheritance. If JavaScript is available, then inheritance shall be specified that way, otherwise the fallback of the element should have nothing to do with JavaScript inheritance (and HTML doesn't care about the inheritance at that point because JavaScript is not enabled to begin with!).

The outcome of my points above is that now the `is=""` attribute doesn't specify inheritance at all, it is **strictly a tool for progressive enhancement** which is the only reason in this thread that people want the `is=""` attribute, so if we keep it lets make the API clean. If the value of `is=""` is an element that happens to extend the element that owns the `is=""` attribute, then that should be considered only a coincidence, but it should not be a requirement.

For example, this should be possible: `<video is="awesome-button">` where when `awesome-button` is not defined, a video (HTMLVideoElement) is played on the screen, and when `awesome-button` is defined (and extends from HTMLButtonElement) then a button with button behavior is seen on the screen. Maybe the user's progressive enhancement idea in this example is to show a video that makes fun of the end-user who has an outdated browser that doesn't support custom elements, and makes them feel like they should get a new browser!

@prushforth I think you missed the idea that @oleersoy (and me too after I realized the same fact that you are pointing out) has been trying to convey multiple times: that browsers should not share interfaces across multiple elements, but rather that browsers should implement a single class per element. See my points 1 and 2 above.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/webcomponents/issues/509#issuecomment-266065705

Received on Friday, 9 December 2016 17:03:33 UTC