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

Document passing information from a component to a function slot #8855

Closed
Fryuni opened this issue Jul 18, 2024 · 8 comments
Closed

Document passing information from a component to a function slot #8855

Fryuni opened this issue Jul 18, 2024 · 8 comments
Labels
add new content Document something that is not in docs. May require testing, confirmation, or affect other pages. help wanted Issues looking for someone to run with them!

Comments

@Fryuni
Copy link
Member

Fryuni commented Jul 18, 2024

📚 Subject area/topic

Slots

📋 Suggested page

https://docs.astro.build/en/basics/astro-components/#slots

📋 General description or bullet points (if proposing new content)

🖥️ Reproduction of code samples in StackBlitz

https://stackblitz.com/edit/github-oqp5kf?file=src%2Fcomponents%2FMyList.astro,src%2Fpages%2Findex.astro

@Fryuni Fryuni added the add new content Document something that is not in docs. May require testing, confirmation, or affect other pages. label Jul 18, 2024
@Soviut
Copy link

Soviut commented Jul 19, 2024

I originally asked about this because I use Vue's "scoped slots" a lot. https://vuejs.org/guide/components/slots.html#scoped-slots

It would be great if this pattern was given its own sub-section and named "Scoped slots". While the approach from Vue is very different, it would at least convey the intent.

@Soviut
Copy link

Soviut commented Jul 19, 2024

For context, here's what I was demonstrating with Vue in the Discord

in the long term what i'm hoping for is this (note: Vue syntax)

MyList.vue (component)

<script setup lang="ts">
defineProps<{
  items: string[]
}>()
</script>

<template>
  <ul>
    <li v-for="(item, index) in items">
      <slot :item="item" :index="index" :total="items.length" />
    </li>
  </ul>
</template>

Index.vue (usage)

<MyList :items="items" v-slot="{ item, index, total }">
  <div>
    {{item}}
    <span>( {{index}} / {{total}} )</span>
  </div>
</MyList>

Note how the v-slot yields not only the item but also additional context like the index and total from within the component.

Here is a slightly modified Stackblitz that @Fryuni sent to me that does the same thing in Astro
https://stackblitz.com/edit/github-oqp5kf-ozddjd?file=src%2Fcomponents%2FMyList.astro,src%2Fpages%2Findex.astro

---
const { items } = Astro.props;
---
<ul>
  {items.map((item, index, list) => (
    <li set:html={Astro.slots.render('default', [item, index, list])} />
  ))}
</ul>
<MyList items={numbers}>
  {(item, index, list) => (
    <>
      Item {index}:
      <ul>
        <li>Value: {item}</li>
        <li>Last occurrence: {list.lastIndexOf(item)}</li>
      </ul>
    </>
  )}
</MyList>

While I prefer the Vue syntax, this makes it clear that scoped slots are possible.

@sarah11918
Copy link
Member

Thanks for creating this issue! Is @BryceRussell 's comment on Discord relevant to capture here, too? https://discord.com/channels/830184174198718474/872579324446928896/1263701298591698954

When passing functions to named slots, does not work, it has to be a html tag that does not contain a - like: , or , etc

<YourAstroComponent>
  <fragment slot="with-options">
    {() => ...}
  </fragment>
</YourAstroComponent>

Issue: withastro/astro#6683

@BryceRussell
Copy link
Member

BryceRussell commented Jul 19, 2024

I think it would be great to document named slot functions, but it will be tricky.

The default assumption user's have when passing named slot functions is to use a <Fragment>:

<Component>
	<Fragment slot="one">
		{() => ...}
	</Fragment>
</Component>

But due to the way Astro renders components/slots this is not possible. Instead, users have to use a HTML tag to pass the function to a slot:

<Component>
	<fragment slot="one">
		{() => ...}
	</fragment>
</Component>

But this syntax some issues because it feels hacky:

  • The wrapping HTML tag does NOT get rendered, it is only used to pass the function to a slot. This is confusing because it is the only case where an HTML tag inside a file does not get included in the final output.
  • The HTML tag name is arbitrary, which can be confusing because examples that do the same thing can look very different (see example below)
  • The tag name cannot be slot or include a dash - (like you would typically use for web components)
// These example do the same thing but the last 3 examples are less explicit and more confusing than the first

<Component>
	<fragment slot="one">
		{() => ...}
	</fragment>
</Component>

<Component>
	<f slot="one">
		{() => ...}
	</f>
</Component>

<Component>
	<one slot="one">
		{() => ...}
	</one>
</Component>

<Component>
	<div slot="one">
		{() => ...}
	</div>
</Component>

@sarah11918
Copy link
Member

Thanks Bryce! While maybe not "quick" to document, you've laid out the pattern very well in a way that makes sense and I do think we could get that into docs.

@Soviut if you had seen documentation like Bryce's post above, would that have answered your original question, and would you have been able to work from that?

@sarah11918 sarah11918 added the help wanted Issues looking for someone to run with them! label Jul 29, 2024
@sarah11918
Copy link
Member

@BryceRussell would you be willing to make an attempt to put a PR together for docs based on what you added above?

I will add this to the list of improvements I think we should totally make!

@BryceRussell
Copy link
Member

BryceRussell commented Jul 29, 2024

@sarah11918 Ya, no problem, I can tackle this issue

@sarah11918
Copy link
Member

closing this as partially addressed by 8946, and i think good for now for what we want to call attention to as happy path behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
add new content Document something that is not in docs. May require testing, confirmation, or affect other pages. help wanted Issues looking for someone to run with them!
Projects
None yet
Development

No branches or pull requests

4 participants