```
Whoa!! What's going on here?
Notice there is no slot definition in the html portion of the component. Instead, what we do is have _Astro_ render the slot content (here, the 'default' content, but you can also render named slots) into a variable, and then use that content in a _div_ (for instance).
So, if the usage is in a markdown file, like so:
```mdx
import MyComponent from '../../components/MyComponent';
# Using the above component in a .mdx file (that can take components)
### Here is some markdown content
- With a bullet item.
```
_MyComponent_ renders the markdown to html and then injects it into the div.
This actually has a big advantage -- consider that with the normal usage you don't have access to the slot contents: _Astro_ just plops the content into the _<slot/>_ tag. Using this method, however, allows you to access the content and further manipulate it before it gets inserted into the html.
This allows a great deal of flexibility in component design.
### Yet Another Step
Now, we get to the techniques used in _AstroWind_, we'll use the _pages/index.astro_ file to illustrate.
You'll note that the index file imports a lot of components, each one roughly analagous to a panel in the index page. Each of these components, in turn, is instantiated sequentially throughout the page. But, you'll notice that some of them use this kind of construct (we'll use the last section, _CallToAction_, as it is most illustrative of the technique):
```astro
Astro +
Tailwind CSS
Be very surprised by these huge fake numbers you are seeing on this page.
Don't
waste more time! :P
```
Some things to note, here:
This argument is actually being passed a javascript object -- not a string. (However, in the TS definition, it could be a string...)
Furthermore, these <Fragment/> elements each have a _slot="(value)"_ specifier.
The latter seems odd, because <Fragment/> is a built-in component over which you have no control, and doesn't have a provision for rendering slots,
per se.
The answer lies in a paragraph in the _Astro_ docs, slots section, which states:
> Use a `slot="my-slot"` attribute on the child element that you want to pass through to a matching slot `name="my-slot" />` placeholder in your component.
That's pretty concise and a bit of a head-scratcher to read, but basically what it says is that:
1. Given a component that defines a slot:
1. you can reference a slot from a child element of that component and,
1. provide content to the parent component's slot from the child by naming the slot in the child with a `slot="
"` property assignment, where the _slot-name_ is the parent's slot.
So, in the example above, the _CallToAction_ component defines the _subtitle_ slot, and the following _<Fragment slot="subtitle">_ populates the slot with the following content:
```astro
Be very surprised by these huge fake numbers you are seeing on this page.
Don't
waste more time! :P
```
And, the _CallToAction_ component defines and renders it thusly:
```astro
---
...
const {
subtitle = await Astro.slots.render('subtitle'),
} = Astro.props;
---
...
{subtitle && }
...
```
There's a lot to wrap your head around, here.
Notice first that _subtitle_ is defined as a prop/argument, but it's being processed as a slot. Interestingly, prop args and slots seem to be somewhat interchangeable: if the subtitle was just a string, it would simply take that assignment. The main difference is that if you render them independently, you have to call the render with an _await_ modifier.
## CallToAction Property
Note: |
There's a _lot_ of duplicate (or at least very similar code) in the following components, especially as regards the _CallToAction_ mechanism -- adding to a lot of confusion and something of a maintenance headache:
src/components/widgets/Hero.astro
src/components/widgets/Steps2.astro
src/components/widgets/CallToAction.astro
src/components/widgets/Hero2.astro
src/pages/landing/startup.astro
Seems like this could be cleaned up.
|
The _CallToAction_ property can be of type `string | CallToAction` where the `CallToAction` is a typed object. In the component, this is handled thusly:
```astro
---
const {
callToAction = await Astro.slots.render('callToAction'),
} = Astro.props;
// also rendered as a slot
---
...
{
typeof callToAction === 'string' ? (
) : (
callToAction &&
callToAction.text &&
callToAction.href && (
)
)
}
```
First, the property type is checked to see if it's a string: if so, it's just set into a child _<Fragment>'s_ html.
If not, it is validated as an object and then members of the object are assigned to various
html elements.