skip to Main Content

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.)

2

Answers


  1. 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)

    Login or Signup to reply.
  2. You can use the $$restProps object to pass all the events and properties of 
    the button to the component:
    
    <script>
      import { createEventDispatcher } from "svelte";
    
      const dispatch = createEventDispatcher();
    
      export let $$restProps;
    </script>
    
    <button on:click={() => dispatch("click")} {...$$restProps}>
    <slot />
    
    <style>
      button {
        /* ... */
      }
    </style>
    

    Then use this component like this:

    <StyledButton class="my-button" on:click={() => console.log("clicked!")}>
      Click me!
    </StyledButton>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search