Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/content/docs/en/guides/content-collections.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ const posts = await getCollection('blog');
))}
</ul>
```
#### Rendering body content
#### Rendering body content

Once queried, you can render Markdown and MDX entries to HTML using the [`render()`](/en/reference/modules/astro-content/#render) function property. Calling this function gives you access to rendered HTML content, including both a `<Content />` component and a list of all rendered headings.

Expand All @@ -420,6 +420,8 @@ const { Content, headings } = await render(entry);
<Content />
```

<ReadMore>When working with MDX entries, you can also [pass your own components to `<Content />`](/en/guides/integrations-guide/mdx/#passing-components-to-mdx-content) to replace HTML elements with custom alternatives.</ReadMore>

#### Passing content as props

A component can also pass an entire collection entry as a prop.
Expand Down
66 changes: 43 additions & 23 deletions src/content/docs/en/guides/integrations-guide/mdx.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -185,27 +185,22 @@ Here is my counter component, working in MDX:
<ReactCounter client:load />
```

#### Custom components with imported MDX
#### Assigning Custom Components to HTML elements

With MDX, you can map Markdown syntax to custom components instead of their standard HTML elements. This allows you to write in standard Markdown syntax, but apply special component styling to selected elements.

When rendering imported MDX content, [custom components](#assigning-custom-components-to-html-elements) can be passed via the `components` prop.
For example, you can create a `Blockquote.astro` component to provide custom styling for `<blockquote>` content:

```astro title="src/pages/page.astro" "components={{...components, h1: Heading }}"
```astro title="src/components/Blockquote.astro"
---
import { Content, components } from '../content.mdx';
import Heading from '../Heading.astro';
const props = Astro.props;
---
<!-- Creates a custom <h1> for the # syntax, _and_ applies any custom components defined in `content.mdx` -->
<Content components={{...components, h1: Heading }} />
<blockquote {...props} class="bg-blue-50 p-4">
<span class="text-4xl text-blue-600 mb-2">“</span>
<slot /> <!-- Be sure to add a `<slot/>` for child content! -->
</blockquote>
```

:::note
Custom components defined and exported in an MDX file must be imported and then passed back to the `<Content />` component via the `components` property.
:::

#### Assigning Custom Components to HTML elements

With MDX, you can map Markdown syntax to custom components instead of their standard HTML elements. This allows you to write in standard Markdown syntax, but apply special component styling to selected elements.

Import your custom component into your `.mdx` file, then export a `components` object that maps the standard HTML element to your custom component:

```mdx title="src/blog/posts/post-1.mdx"
Expand All @@ -215,17 +210,42 @@ export const components = {blockquote: Blockquote}
> This quote will be a custom Blockquote
```

Visit the [MDX website](https://mdxjs.com/table-of-components/) for a full list of HTML elements that can be overwritten as custom components.

```astro title="src/components/Blockquote.astro"
:::note
Custom components defined and exported in an MDX file must always be imported and then passed back to the `<Content />` component via the `components` property.
:::

#### Passing `components` to MDX content

When rendering imported MDX content with the `<Content />` component, including rendering MDX entries using content collections, custom components can be passed via the `components` prop. These components must first be imported to make them available to the `<Content />` component.

The `components` object maps HTML element names (`h1`, `h2`, `blockquote`, etc.) to your custom components. You can also include [all components exported from the MDX file itself](#assigning-custom-components-to-html-elements) using the spread operator (`...`), which must also be imported from your MDX file as `components`.

If you are importing MDX directly from a single file for use in an Astro component, import both the `Content` component and any exported components from your MDX file.

```astro title="src/pages/page.astro" "components={{...components, h1: Heading }}" {2}
---
const props = Astro.props;
import { Content, components } from '../content.mdx';
import Heading from '../Heading.astro';
---
<blockquote {...props} class="bg-blue-50 p-4">
<span class="text-4xl text-blue-600 mb-2">“</span>
<slot /> <!-- Be sure to add a `<slot/>` for child content! -->
</blockquote>
<!-- Creates a custom <h1> for the # syntax, _and_ applies any custom components defined in `content.mdx` -->
<Content components={{...components, h1: Heading }} />
```

If your MDX file is a content collections entry, then use the `render()` function from `astro:content` to access the `<Content />` component.

The following example passes a custom heading to the `<Content />` component via the `components` prop to be used in place of all `<h1>` HTML elements:

```astro title="src/pages/blog/post-1.astro" ins="components={{ h1: CustomHeading }}"
---
import { getEntry, render } from 'astro:content';
import CustomHeading from '../../components/CustomHeading.astro';
const entry = await getEntry('blog', 'post-1');
const { Content } = await render(entry);
---
<Content components={{ h1: CustomHeading }} />
```
Visit the [MDX website](https://mdxjs.com/table-of-components/) for a full list of HTML elements that can be overwritten as custom components.

## Configuration

Expand Down Expand Up @@ -378,7 +398,7 @@ export default defineConfig({

Previously known as `customComponentNames`.

An optional property of `optimize` to prevent the MDX optimizer from handling certain element names, like [custom components passed to imported MDX content via the components prop](/en/guides/integrations-guide/mdx/#custom-components-with-imported-mdx).
An optional property of `optimize` to prevent the MDX optimizer from handling certain element names, like [custom components passed to imported MDX content via the components prop](#passing-components-to-mdx-content).

You will need to exclude these components from optimization as the optimizer eagerly converts content into a static string, which will break custom components that needs to be dynamically rendered.

Expand Down
2 changes: 1 addition & 1 deletion src/content/docs/en/reference/directives-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ These directives control how [UI Framework components](/en/guides/framework-comp

By default, a UI Framework component is not hydrated in the client. If no `client:*` directive is provided, its HTML is rendered onto the page without JavaScript.

A client directive can only be used on a UI framework component that is directly imported into a `.astro` component. Hydration directives are not supported when using [dynamic tags](/en/reference/astro-syntax/#dynamic-tags) and [custom components passed via the `components` prop](/en/guides/integrations-guide/mdx/#custom-components-with-imported-mdx).
A client directive can only be used on a UI framework component that is directly imported into a `.astro` component. Hydration directives are not supported when using [dynamic tags](/en/reference/astro-syntax/#dynamic-tags) and [custom components passed via the `components` prop](/en/guides/integrations-guide/mdx/#passing-components-to-mdx-content).

### `client:load`

Expand Down