Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce svelte:composable #7851

Open
mimbrown opened this issue Sep 10, 2022 · 2 comments
Open

Introduce svelte:composable #7851

mimbrown opened this issue Sep 10, 2022 · 2 comments

Comments

@mimbrown
Copy link
Contributor

Describe the problem

Svelte handles composability on the logic level quite well, with first-class support for stores. But composability on the HTML element level is a little bit lacking. The use:action feature is great for adding composable features, but to define an action you just write a function, without the benefit of any sveltiness. But things like classes and event listeners are inherently composable, so it's a shame that it's not simple to make use of that in an ergonomic way.

Along with this, IMO we think too quickly of reusable components instead of composition. For an example, consider the Svelte Material UI library (not trying to pick on this, it just illustrates the point). If you look at the svelte component for a MaterialButton, you'll see all the hallmarks of a component that should be a composable; things like:

  • <svelte:component this={component}
  • use={[/* ..., */ forwardEvents, ...use ]}
  • The dreaded {...$$restProps}
  • {href} (just in case the consumer wants to use a link, etc.)

In summary, the author of this reusable component had to consider: what are all the ways a consumer of this component might conceivably want to use it? I need to make sure I make the underlying semantic element dynamic, pass down all the correct attributes and forward all the expected events, merge all the internal and external classes, etc etc. This should not be.

Describe the proposed solution

I would like the ability to write a svelte composable in a similar way to the way we write svelte components, with full compiler support, that compiles to an Action function instead of a Component. For type reasons, it would probably have to be a separate file extension, something like .svelte-composable (way too long, I know). In composable files, I would envision that we can have <script>, <script context="module">, and <style> blocks as normal, but instead of other HTML elements we would have a single <svelte:composable> element. Here's a simplified example of the code I would want to write when defining something like a material button:

<!-- ripple.svelte-composable -->

<script>
function handleClick(event) {
  // Do the ripple
}
</script>

<svelte:composable class="ripple-container" on:click={handleClick} />

<style>
.ripple-container {
  /* ... */
}
</style>
<!-- button.svelte-composable -->

<script>
import ripple from "./ripple.svelte-composable";
</script>

<svelte:composable class="material-button" use:ripple />

<style>
.material-button {
  /* ... */
}
</style>
<!-- raisedButton.svelte-composable -->

<script>
import button from "./button.svelte-composable";
</script>

<svelte:composable class="material-button--raised" use:button />

<style>
.material-button--raised {
  /* ... */
}
</style>
<!-- userland.svelte -->

<script>
import raisedButton from "some-material-lib/raisedButton.svelte-composable";
</script>

<button use:raisedButton>
  I'm a button
</button>

<a use:raisedButton href="#">
  I'm a link
</a>

Alternatives considered

No alternatives that I've personally considered, but there's a lot of considerations that would be non-trivial. Here's a few:

  1. How would style scoping be handled?
  2. Could a <svelte:composable> element have children? What exactly would that mean (order of insertion, etc)?
  3. How difficult would it be to update the compiler to handle this?

Importance

would make my life easier

@Prinzhorn
Copy link
Contributor

Prinzhorn commented Sep 10, 2022

sveltejs/rfcs#41

What you describe is exactly what I want declarative actions to be. And Svelte should be able to compile them to the same declarative code that vanilla actions already use with 100% backwards compat.

The comments I made in that rfc should resonate with you, e.g.

I realized that declarative actions would change my mental model for actions.;

  • Currently: actions are my escape hatch into the DOM world and I can do with the node whatever I want
  • New: actions allow horizontal extension of elements. In contrast to the component system (with composition/context etc.) which are all vertical.

@mimbrown
Copy link
Contributor Author

@Prinzhorn Thanks, that is a very similar proposal, though it looks a bit like it's heading in a different direction. I've added my thoughts over there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants