Markdoc pages use tags instead of imports. @pelagornis/page/markdoc ships a preset that registers tags for the RefineUI components that render without client state. This page is an .mdoc file, so every example below is rendered by those tags.
Install Markdoc
Section titled “Install Markdoc”bun add @astrojs/markdoc @astrojs/starlight-markdocAdd the Markdoc integration before Starlight.
import markdoc from "@astrojs/markdoc";import starlight from "@astrojs/starlight";import pagePlugin from "@pelagornis/page";import { defineConfig } from "astro/config";
export default defineConfig({ integrations: [ markdoc(), starlight({ title: "My Docs", plugins: [pagePlugin()], }), ],});Add the preset
Section titled “Add the preset”Create markdoc.config.mjs next to the Astro config. starlightMarkdoc() brings Starlight's own tags such as aside. pageMarkdoc() adds the RefineUI tags.
import { defineMarkdocConfig } from "@astrojs/markdoc/config";import starlightMarkdoc from "@astrojs/starlight-markdoc";import pageMarkdoc from "@pelagornis/page/markdoc";
export default defineMarkdocConfig({ extends: [starlightMarkdoc(), pageMarkdoc()],});Write tags
Section titled “Write tags”Attributes use the React prop names and values. A tag with content needs a matching closing tag. A tag without content closes itself with a slash before the final %}.
{% stack direction="row" gap="sizeSmall" align="center" %}{% badge variant="success" %}Stable{% /badge %}{% button variant="primary" %}Continue{% /button %}{% button variant="outline" %}Cancel{% /button %}{% /stack %}Stable
Numbers and booleans are written without quotes.
{% progress value=60 ariaLabel="Upload" /%}{% checkbox label="Send release emails" defaultChecked=true /%}Use ariaLabel where the React prop is aria-label. Every tag also accepts class and id.
Tags in the preset
Section titled “Tags in the preset”| Tag | Component | Notes |
|---|---|---|
box, container, grid, stack, spacer | Box, Container, Grid, Stack, Spacer | Layout with token props |
divider | Divider | Content becomes the inline label |
text | Text | variant defaults to bodyMd |
button, link | Button, Link | link requires href |
label, input, textarea, checkbox, radio | Form controls | Native inputs, no client script |
badge, chip | Badge, Chip | Content is the label |
progress, spinner, skeleton | Feedback | progress requires value |
icon | WebIcon | name is a RefineUI icon name |
avatars | Avatars | avatars=[{alt: "Name"}] |
Add a tag for an interactive component
Section titled “Add a tag for an interactive component”Tags render Astro components on the server. A component with client state needs an .astro wrapper that hydrates it. Compose the component in a .tsx file as described in Use in MDX, then wrap it.
---import TabsExample from "../TabsExample";---
<TabsExample client:load />Register the wrapper next to the preset.
import { component, defineMarkdocConfig } from "@astrojs/markdoc/config";import starlightMarkdoc from "@astrojs/starlight-markdoc";import pageMarkdoc from "@pelagornis/page/markdoc";
export default defineMarkdocConfig({ extends: [starlightMarkdoc(), pageMarkdoc()], tags: { "tabs-example": { render: component("./src/components/markdoc/TabsExample.astro"), selfClosing: true, }, },});{% tabs-example /%}Each component page lists the Markdoc tag for that component, or the wrapper to write when it needs one.