Closed kylebutts closed 1 year ago
in the example, there is a glob for all of the content, '../content/*.mdx'. It is rare that markdown has one .astro file per .md file, so simply shifting the components from where its used to the layout, might not improve visibility. Also, the layout, is no special component, but any component can have slots. The interesting concept here is how to create a context for child slot component without having to pass them in each step (avoids prop drilling), and that could be solved in a generic way not just for a specific component variable.
Want to +1 here, and also mention another flawed alternative: it is possible to bulk export the whole components
object with all the component associations, making it a single line you'd need to use in your .mdx:
export { components } from '../components/index.js';
This works for regular components, but, playing with the code a bit (just starting with astro, so might be mistaken) there seems to be no way to create an index file like this and export multiple astro components into it? So this method would work only for non-astro components, and the main issue with this is that it won't then be possible to use client directives for those components.
Having an easy way to export a list of mdx components from a layout component would be a very welcomed feature!
Thanks for opening this proposal @kylebutts! Sorry it took us so long to respond.
With the new Content Collections feature, Astro is moving away from the magic layout
pattern.
While it's still possible to use, we'd recommend that new projects use Content Collections and declaratively pass their components
to the Content
component as a prop.
We're hopeful that this pattern addresses the limitations of the previous pattern that this proposal was attempting to solve. If you'd like to continue this discussion, we encourage you to open a new Stage 1 Proposal and link back to this proposal!
Thanks @natemoo-re; I think Content Collections works wonderfully!
Summary
Include custom MDX components (e.g. h1-6, p, ol, etc.) in
layout
components.Example
If the proposal involves a new or changed API, then;
Motivation
Currently, if you want to have a set of custom components for your MDX documents, you need to import (and export) them at the start of each file:
This either (i) creates a lot of boilerplate that needs to be copied to each new file, (ii) style content (in a somewhat constrained way) in the layout component by using css with tag selectors, or (iii) requires programming a custom router page like:
Detailed design
I propose to include a
components
option in a layout component's frontmatter. Currently, Astro already implements alayout
option for MDX in the frontmatter, which seems like a natural place to bundle both the structure of the page and the components that would be rendered with MDX.For example, an API could be something like:
Then, when the MDX uses the layout, these components could be used to render the appropriate tags.
I'm not exactly sure how to implement this feature. It seems like the way layout components are used is in a rehype plugin (which occurs after MDX processes the file). It could be possible to inject the import and export code during this step but that might be difficult in the proposed API since the exported
components
object is the actual components, and not strings. I suspect doing it similar to the way the custom router above does it is the best way, but I really don't know enough about the underlying code powering Astro to say exactly what the best strategy would be.Drawbacks
One potential drawback is that this is an MDX specific feature, which could be confusing if for example, people expect their HTML tags (e.g.
<h1>
) to be transformed in their.astro
pages when using their<MdxLayout>
layout. That of course could be mitigated with proper documentation of the feature.Alternatives
Three alternatives were described above:
(i) Import and export components in each mdx file.
(ii) Style content (in a somewhat constrained way) in the layout component by using css with tag selectors. For example,
This way works well for styling, but doesn't allow you to do any processing or wrap in custom components.
(iii) requires programming a custom router:
Adoption strategy
Unresolved questions
I'm not sure what the best path forward in actual implementation of this feature which is obviously an important question to get right.