sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
78.04k stars 4.08k forks source link

Svelte5: default snippet inside component and overwriting on consuming #11914

Closed Dudek-AMS closed 2 months ago

Dudek-AMS commented 2 months ago

Describe the problem

Following Discussion: https://discord.com/channels/457912077277855764/1247891680183717909 I don't like the actual way how snippets are defined inside components. If I want the user be able to overwrite a snippet but also have a default snippet I have to "declare two names". Something like

<script>
  let { snippetHeader = snippetDefaultHeader } = $props();
</script>
{#snippet snippetDefaultHeader()}
myDefaultContent
{/snippet}

{@render snippetHeader())

The old slot way felt way better to solve this

Describe the proposed solution

At first sight, i thought that having some magic the compiler detecting same property/snippet name would be cool, so I dont have to use a second name for the snippet and set the default value on my own. But this could be ambigious. So I guess extending the {#snippet ...} to do some magic should be cleaner and more obvious so my proposed solution is this:

<script>
  //MyComp.svelte
  let { ...someOtherArgss } = $props();
</script>
{#snippetProp  snippetHeader()}
myDefaultContent
{/snippetProp}

{@render snippetHeader())
<MyComp />

Renders: myDefaultContent

<MyComp>
{#snippet snippetHeader()}
myCustomContent
{/snippet}
</MyComp>

Renders: myCustomContent

Importance

nice to have

MotionlessTrain commented 2 months ago

This can work too:

{#if snippetHeader}
  {@render snippetHeader()}
{:else}
  myDefaultContent
{/if}

No need for a second snippet name when done like this

Dudek-AMS commented 2 months ago

snippets can take params and the aim is to remove the markup from the logic, so this is not a good alternative

paoloricciuti commented 2 months ago

snippets can take params and the aim is to remove the markup from the logic, so this is not a good alternative

Wdym by "snippets can take params"? snippetHeader could also take a param in this case.

Dudek-AMS commented 2 months ago

right from the docs

{#snippet figure({ src, caption, width, height })}
    <figure>
        <img alt={caption} {src} {width} {height} />
        <figcaption>{caption}</figcaption>
    </figure>
{/snippet}

also you gonna lose the possiblity to pass the 'defaultSnippet' to another Component

brunnerh commented 2 months ago

If you actually need a default snippet to further pass around, you can define it as necessary. This does not seem all that common of a requirement.

If you have default content in an else branch, you can directly use the variables in scope, the only thing the snippet adds is destructuring, which can be done with @const.

{#if snippetHeader}
  {@render snippetHeader(data)}
{:else}
  {@const { a, b, c } = data}
  ...
{/if}

Do not see an issue with arguments here.

dummdidumm commented 2 months ago

All these use cases can be solved with if/else blocks or fallback snippets being applied. We're not going to introduce different syntax for this, therefore closing.