4

I realise this is not a support forum; I am trying to sneak this in as a documentation request.

Short question: what's the recommended way of creating elements that behave exactly the same as native ones, in all respects? (offering extras, yes, but being 100% compatible drop-in replacement of native ones)

Long version:

I need to extend the native <button> element. The goal is to create a "super button" which can be used as a 100% drop-in replacement of the native HTML button (but obviously offers extra functionality that consumers can use or not). Please note that I am leaving styling totally out of the equation here. So...

Way 1: Inherit from Button

In Polymer, it's always been clear that you cannot inherit from a native element. I assume this is still the case?

Way 2: Compose

Following this way, I have a <button> in the shadow dom, and reflect all attributes and properties (meaning that any change to my-button will be reflected to the button element in the shadow DOM). [EDITED: the element won't need to reflect all events, thanks to shadow DOM's retargeting of events]

For "Way 2", it would mean a lot of attribute replication, etc. This can be done fairly easily with lit-element (the behaviour for all attributes would be identical, and it would apply for a rather long list of them). But... before I get to it, am I entering a rabbit hole?

I can think of so many things that can go wrong... for example, should I even bother reflecting tabindex? Will the form attribute even works, since the button will be in a shadow root? And so on and so forth.

So... Is there an easy way to replicate 100% of the functionality of a specific HTML element without having to reflect each single attribute? And would it work?

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Merc
  • 16,277
  • 18
  • 79
  • 122
  • First that come into my mind is [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy). Revocable eventually. – bigless Apr 20 '19 at 23:56
  • Would you proxy the native element? Or the custom element I am creating? – Merc Apr 21 '19 at 01:01

1 Answers1

2

Option 1) isn't really widely supported - Google were pushing for it when Polymer released, but now it seems a very long way down the list of features Safari will probably never get round to. Lit doesn't really support it. You could use lit-html as part of your render, but LitElement is really about making your own components quickly and easily rather than extending built in ones.

I'd say 2) - if you want a 'super button' that's probably the only way, even if reflecting all the properties is a pain.

However, if you just want to extend button behaviour you might be able to use Lit directives and element expressions. New to Lit 2 (and with most examples are still in labs) element expressions let you set up multiple attributes, properties and events in a single directive. It it would look something like:

html`<button ${superButtonFeature()}>Click Me</button>`

A really good example of the kind of behaviours possible is FLIP animations.

Keith
  • 150,284
  • 78
  • 298
  • 434