PreviewFrame

PreviewFrame is the wrapper that turns a ```razor:preview fenced code block into a live demo : the component renders on top, the source is collapsed underneath a "View Code" gutter that expands on click.

You don't reference PreviewFrame directly

It's the chrome behind the razor:preview fence. Author your live examples as fenced code : the framework wraps them in PreviewFrame for you. You'd only touch PreviewFrame explicitly if you're rendering custom pages outside DocsPage.

What it looks like

Every live example on this site uses PreviewFrame under the hood. Here's one you've seen already:

The frame has two regions:

Prop Type Default Description
Render region top The live `DynamicComponent` instance : real Blazor, full interactivity.
Source region bottom Shiki-highlighted source, collapsed by default. `View Code` expands; `Collapse` re-collapses. When expanded, a copy button surfaces.

How the fence becomes a PreviewFrame

The ShellDocs.Markdown pipeline detects the fence language razor:preview, parses the tag inside (component name + attributes + child content), resolves the target Type via TypeRegistry, and emits a PreviewSlot marker. At render time, MarkdownContent swaps the marker for a <PreviewFrame Preview="...">.

The upshot: you author fenced razor markup, the framework renders it live and shows the source.

markdown
```razor:preview
<Callout Variant="warning">This is authored as a fenced block.</Callout>
```

Renders as:

razor
<Callout Variant="warning">This is authored as a fenced block.</Callout>

Attribute coercion

The tag inside the fence uses string attributes (Variant="warning"), but the target component's [Parameter] may be typed (enum, int, bool). SlotRenderer.BuildParameters reflects on the target's properties and coerces at render time. So Variant="warning" (string) → the correct enum value, Columns="3" (string) → int, etc.

Child content

Non-self-closing tags carry their inner text as ChildContentRaw. SlotRenderer normalizes indentation (via Dedent), feeds the body to Markdig, and hands the resulting RenderFragment to the target as ChildContent. Consequence: you can use full markdown inside a preview's body : lists, code blocks, nested components.

Copy button

When the source region is expanded, a copy-to-clipboard button appears. It copies the raw fence body (the exact string you authored) : ready to paste into a .razor file. Success flashes a checkmark for ~1.4 s.

Props

Prop Type Default Description
PreviewRequired PreviewSlot The parsed fence data : target type, attributes, raw code, child content. Constructed by the markdown pipeline; you don't build one by hand.

See also