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

A way to spread binds, transitions, actions... #15395

Open
rChaoz opened this issue Feb 26, 2025 · 3 comments
Open

A way to spread binds, transitions, actions... #15395

rChaoz opened this issue Feb 26, 2025 · 3 comments

Comments

@rChaoz
Copy link
Contributor

rChaoz commented Feb 26, 2025

Describe the problem

This has been a common problem in Svelte for long. I like the currently cooking attachments (#15000) PR that aims to solve this, but I think deprecating transitions/other directives won't happen very soon, and a solution for them would be nice.

Describe the proposed solution

Attachments can be applied using symbols. I don't like that any symbol is treated as an attachment - string props are already all used, and using all symbols disallows adding additional stuff in the future. Why not...

<script>
  import { Bind, Transition, Use } from "svelte/symbols"

  const boundProps = $state({ ... })
  const props = {
    [Bind]: boundProps,
    [Transition]: [fade, { duration: 1000 }],
    [Use]: ...
  }
</script>

<Component {...props} />
<!-- Component.svelte -->
<script>
  let { a = 5, b = $bindable(), ...rest } = $props()
</script>

<div {...rest} >
  ...
</div>

where svelte/symbols is something like:

export const Transition = Symbol.for("svelte:transition")
...

I think typescript also plays nice with such symbols.

Importance

nice to have

@adiguba
Copy link
Contributor

adiguba commented Feb 26, 2025

Hello,

Having a way to set a transition (or animate) on a component would be nice.
Same for actions...

But for bindings I think this could cause conflicts with the internal stuffs of the component.

Also, I think this can be done with anothers parameters of the components instead of props.
Ex: actually a component create a function like that :

export default function Component($$anchor, $$props) {
	
}

If we allow special directives on components, we could use a third argument for that :

export default function Component($$anchor, $$props, $$directives) {
	
}

And IMHO, I think this need a special syntax, allowing us to separate them from spreading if we dont want to use that.

@adiguba
Copy link
Contributor

adiguba commented Feb 26, 2025

Thinking at that, perhaps a solution would be to use something like transition:this, animate:this and use:this

Exemple :

<!-- spread the props -->
<div {...rest}></div>

<!-- spread transitions -->
<div transition:this></div>

<!-- spread animate (must be on the root of the component) -->
<div animate:this></div>

<!-- spread actions -->
<div use:this></div>

<!-- spread props, transitions, animate and actions -->
<div {...rest} transition:this animate:this use:this></div>

@rChaoz
Copy link
Contributor Author

rChaoz commented Feb 26, 2025

There are a lot of ways to implement this, and there have been many suggestions in the past. The point of this post is that this could be done very similarly to the new attachments, which seems like the current direction. Attachments would also go well together this: { [Attachments]: ... }.

But for bindings I think this could cause conflicts with the internal stuffs of the component.

Yes, they'd have to be handled separately.

Thinking at that, perhaps a solution would be to use something like transition:this, animate:this and use:this

This was also suggested in the past. I think it has some drawbacks, e.g. how can you tell if a transition is passed, how do you declare in TypeScript if the competent can even receive it. With symbols props, this is really easy:

<script lang="ts">
  interface Props {
    [Transition]: ...
  }
  // or Pick<HTMLAttributes, Transition, Use, ...>

  const { [Transition]: transition }: Props = $props()
  if (transition != null)  { ... }
</script>

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