Skip to content

Commit

Permalink
Update guidance on named slots in framework components (#824)
Browse files Browse the repository at this point in the history
* feat: update guidance on named slots in framework components

* Update framework-components.md

* Update src/pages/en/core-concepts/framework-components.md

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>

* Update framework-components.md

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
  • Loading branch information
natemoo-re and sarah11918 authored Jun 24, 2022
1 parent 4edc7eb commit 6f131d3
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 8 deletions.
4 changes: 2 additions & 2 deletions src/pages/en/core-concepts/astro-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,8 @@ import Wrapper from '../components/Wrapper.astro';

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.

:::caution
This only works when you’re passing slots to other Astro components. Learn more about including other [UI framework components](/en/core-concepts/framework-components/) in Astro files.
:::tip
Named slots can also be passed to [UI framework components](/en/core-concepts/framework-components/)!
:::


Expand Down
73 changes: 67 additions & 6 deletions src/pages/en/core-concepts/framework-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,32 +119,93 @@ import MyVueComponent from '../components/MyVueComponent.vue';
Only **Astro** components (`.astro`) can contain components from multiple frameworks.
:::

## Passing Children to Framework Components

Inside of an Astro component, you **can** pass children to framework components. Each framework has its own patterns for how to reference these children: React, Preact, and Solid all use a special prop named `children`, while Svelte and Vue use the `<slot />` element.


```astro
// src/pages/MyAstroPage.astro
---
import MyReactSidebar from '../components/MyReactSidebar.jsx';
---
<MyReactSidebar>
<p>Here is a sidebar with some text and a button.</p>
</MyReactSidebar>
```

Additionally, you can use [Named Slots](/en/core-concepts/astro-components/#named-slots) to group specific children together.

For React, Preact, and Solid these slots will be converted to a top-level prop. Slot names using `kebab-case` will be converted to `camelCase`.

```astro
// src/pages/MyAstroPage.astro
---
import MySidebar from '../components/MySidebar.jsx';
---
<MySidebar>
<h2 slot="title">Menu</h2>
<p>Here is a sidebar with some text and a button.</p>
<ul slot="social-links">
<li><a href="https://twitter.com/astrodotbuild">Twitter</a></li>
<li><a href="https://github.com/withastro">GitHub</a></li>
</ul>
</MySidebar>
```

```jsx
// src/components/MySidebar.jsx
export default function MySidebar(props) {
return (
<aside>
<header>{props.title}</header>
<main>{props.children}</main>
<footer>{props.socialLinks}</footer>
</aside>
)
}
```

For Svelte and Vue these slots can be referenced using a `<slot>` element with the `name` attribute. Slot names using `kebab-case` will be preserved.

```jsx
// src/components/MySidebar.svelte
<aside>
<header><slot name="title" /></header>
<main><slot /></main>
<footer><slot name="social-links" /></footer>
</aside>
```

## Nesting Framework Components

Inside of an Astro component, you can also nest components from multiple frameworks.
Inside of an Astro file, framework component children can also be hydrated components. This means that you can recursively nest components from any of these frameworks.

```astro
// src/pages/MyAstroPage.astro
---
import MyReactSidebar from '../components/MyReactSidebar.jsx';
import MyReactButton from '../components/MyReactButton.jsx';
import MySvelteButton from '../components/MySvelteButton.svelte';
---
<MyReactSidebar>
<p>Here is a sidebar with some text and a button.</p>
<MySvelteButton client:load />
<div slot="actions">
<MyReactButton client:idle />
<MySvelteButton client:idle />
</div>
</MyReactSidebar>
```

:::caution
Remember: framework component files themselves (e.g. `.jsx`, `.svelte`) cannot mix multiple frameworks.
:::

This allows you to build entire "apps" in your preferred JavaScript framework and render them, via a parent component, to an Astro page. This is a convenient pattern to allow related components to share state or context.

Each framework has its own patterns for nesting: `children` props and [render props](https://reactjs.org/docs/render-props.html) for React and Solid; `<slot />` with or without names for Svelte and Vue, for example.
This allows you to build entire "apps" in your preferred JavaScript framework and render them, via a parent component, to an Astro page.

:::note
Astro components are always rendered to static HTML, even when they include framework components that are hydrated. This means that you can only pass props that don't do any HTML rendering. Passing React's "render props" or named slots to framework components from an Astro component will not work, because Astro components can’t provide the client runtime behavior that those patterns require.
Astro components are always rendered to static HTML, even when they include framework components that are hydrated. This means that you can only pass props that don't do any HTML rendering. Passing React's "render props" to framework components from an Astro component will not work, because Astro components can’t provide the client runtime behavior that those patterns require. Instead, use named slots.
:::

## Can I Hydrate Astro Components?
Expand Down

0 comments on commit 6f131d3

Please sign in to comment.