Search code examples
csssveltesvelte-3

Is there a good way to style HTML elements and re-expose all of their events in a Svelte component?


How would I go about styling HTML elements and re-exposing all of their events in a Svelte component? (essentially, I'm looking for the Svelte way to do styled-components)

For example, I'm trying to style a regular HTML button and expose it a reusable component:

<script>
  import { createEventDispatcher } from "svelte";

  const dispatch = createEventDispatcher();
</script>

<button
  on:click={() => dispatch("click")}
  on:mouseover={() => dispatch("mouseover")}
  {/* ...and so on for every other event */}
>
  <slot />
</button>

<style>
  button {
    /* ... */
  }
</style>

Is there any way to avoid having to make every single event on the button HTML element call dispatch to propagate the event through the parent? Is there a simpler way?

I've tried searching, and most places point me to just use CSS-in-JS, but I don't want to forego all the optimizations having my styles written purely in Svelte give me (lower bundle sizes, better performance, etc.)


Solution

  • You can forward events by just listing them without event handler:

    <button {...$$restProps} on:click on:focus on:hover ...>
    

    No need to dispatch, but you currently cannot automatically forward all events, they still need to be listed. (Issue on that)

    Properties are passed via $$restProps, which includes all not explicitly defined properties (not events). (Docs)