Skip to content
Page

Use in Markdoc

Turn on Markdoc, add the pageMarkdoc() preset, and write RefineUI components as Markdoc tags.

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.

Terminal window
bun add @astrojs/markdoc @astrojs/starlight-markdoc

Add the Markdoc integration before Starlight.

astro.config.ts
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()],
}),
],
});

Create markdoc.config.mjs next to the Astro config. starlightMarkdoc() brings Starlight's own tags such as aside. pageMarkdoc() adds the RefineUI tags.

markdoc.config.mjs
import { defineMarkdocConfig } from "@astrojs/markdoc/config";
import starlightMarkdoc from "@astrojs/starlight-markdoc";
import pageMarkdoc from "@pelagornis/page/markdoc";
export default defineMarkdocConfig({
extends: [starlightMarkdoc(), pageMarkdoc()],
});

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.

TagComponentNotes
box, container, grid, stack, spacerBox, Container, Grid, Stack, SpacerLayout with token props
dividerDividerContent becomes the inline label
textTextvariant defaults to bodyMd
button, linkButton, Linklink requires href
label, input, textarea, checkbox, radioForm controlsNative inputs, no client script
badge, chipBadge, ChipContent is the label
progress, spinner, skeletonFeedbackprogress requires value
iconWebIconname is a RefineUI icon name
avatarsAvatarsavatars=[{alt: "Name"}]

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.

src/components/markdoc/TabsExample.astro
---
import TabsExample from "../TabsExample";
---
<TabsExample client:load />

Register the wrapper next to the preset.

markdoc.config.mjs
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 /%}
Tabs switch between panes in place.

Each component page lists the Markdoc tag for that component, or the wrapper to write when it needs one.