I'd thought of this as a 'one day' feature, since custom elements aren't universally supported and we already have svelte-custom-elements. But then I started building an Electron app (where custom elements are supported), and started building a UI kit for it (because the nearest thing I could find, photonkit, appears to be abandoned and pertains to an older version of Electron), and it's one of those cases where custom elements really would be quite nice.
svelte-custom-elements sort of works, but it's suboptimal because
- no true style encapsulation (elements aren't shielded from global styles, and you don't get the perf benefits of a local CSSOM)
- there's no light DOM — slotted content becomes part of the shadow DOM
So I think we should add one of the following:
compiled = svelte.compile({
customelement: true,
name: 'x-foo'
});
compiled = svelte.compile({
customelement: 'x-foo'
});
Maybe a component should be able to specify its own name, and customelement: true means 'use the component's self-declared name, or error if it doesn't have one', and customelement: 'x-foo' means 'register this component is <x-foo> whatever it calls itself'.
Differences in input/output that I can think of:
- it would export a class, rather than a constructor function
- styles wouldn't get transformed. (Not entirely sure how styles work tbh — does the
<style> tag need to get attached to every single instance's shadow DOM?)
<slot> elements would get rendered, and options.slots would be ignored (because there would be no options)
- attributes/props need to be part of the component definition (or compiler options, I guess, for situations where the component author didn't anticipate custom element usage)
fire might need to wrap dispatchEvent? Not sure if we'd want to merge on and addEventListener (i.e. mix DOM events together with component events). I think we might have to so that <my-thing on:myEvent='doSomething()'> works. I guess we'd just disable bubbling by default, so that things don't get too wacky
A few nice things that would come out of this:
- Custom elements would still be Svelte components, so you'd still be able to use
set, get, observe
- Svelte components would be elements, so you'd be able to listen for DOM events, style them, add classes, use transitions etc without having to add wrapper elements
- Svelte apps would be able to compile the custom elements with
shared: true so there'd be very little overhead
- Our components would be smaller (and probably faster) than Stencil's 😀
Any thoughts?
I'd thought of this as a 'one day' feature, since custom elements aren't universally supported and we already have svelte-custom-elements. But then I started building an Electron app (where custom elements are supported), and started building a UI kit for it (because the nearest thing I could find, photonkit, appears to be abandoned and pertains to an older version of Electron), and it's one of those cases where custom elements really would be quite nice.
svelte-custom-elements sort of works, but it's suboptimal because
So I think we should add one of the following:
Maybe a component should be able to specify its own name, and
customelement: truemeans 'use the component's self-declared name, or error if it doesn't have one', andcustomelement: 'x-foo'means 'register this component is<x-foo>whatever it calls itself'.Differences in input/output that I can think of:
<style>tag need to get attached to every single instance's shadow DOM?)<slot>elements would get rendered, andoptions.slotswould be ignored (because there would be nooptions)firemight need to wrapdispatchEvent? Not sure if we'd want to mergeonandaddEventListener(i.e. mix DOM events together with component events). I think we might have to so that<my-thing on:myEvent='doSomething()'>works. I guess we'd just disable bubbling by default, so that things don't get too wackyA few nice things that would come out of this:
set,get,observeshared: trueso there'd be very little overheadAny thoughts?