Skip to main content

Preview Modes

frame.mode is the switch that gates isolation entirely — every other frame option below is inert until it's set. Without mode, Live.Preview renders straight into the host document, regardless of any other frame options passed.

  • iframe — isolates the preview in a real iframe document. Note this is not a security sandbox: the code still executes in the host page's JS realm (the sandbox option below controls the iframe's sandbox attribute, which is DOM/CSS isolation, not a security boundary either). Supports every option in the table below.
  • shadow — isolates styles via a shadow DOM host in the same document, without an iframe boundary. scripts, styles, stylesheets, and autoHeight are all silently ignored, since there's no separate document to inject them into. The shadow host only gets whatever CSS naturally inherits across the shadow boundary (font, color, and similar inherited properties) on its own — not utility classes. Two ways to get those working too: syncStyle clones the host document's <link>/<style> tags directly into the shadow root (covers anything already in the host's compiled CSS, including a consuming app's own custom theme tokens), and dynamicTailwind recompiles whatever classes it finds in the rendered DOM at runtime (covers anything the host's build never saw, e.g. a class typed at runtime) — see How Tailwind reaches the preview. The two are complementary and can be used together.
import Live from '@jbpark/live-editor';

const SAMPLE = `
import * as ui from 'ui-kit';

const App = () => (
<div className="p-6 space-y-2">
<ui.Typography.Title level={4}>Preview Modes</ui.Typography.Title>
<ui.Button type="primary">A button</ui.Button>
</div>
);

export default App;
`;

export default function PreviewModes() {
return (
<>
{/* iframe isolation */}
<Live>
<Live.Preview
code={SAMPLE}
dynamicTailwind
frame={{ mode: 'iframe', syncStyle: true }}
/>
</Live>

{/* shadow DOM isolation */}
<Live>
<Live.Preview
code={SAMPLE}
dynamicTailwind
frame={{ mode: 'shadow', syncStyle: true }}
/>
</Live>
</>
);
}

Unlike the other demos on this site, this one is rendered directly in the page — not inside a sandboxed iframe — since it has no reader-authored code to isolate (the sample is a fixed string, not wired to an editor).

frame options

FrameProps (importable from @jbpark/live-editor) is this shape:

OptionTypeApplies toDescription
mode'iframe' | 'shadow'bothIsolation strategy. Omit it and nothing else in this table has any effect.
titlestringiframeThe iframe's title attribute (accessibility).
sandboxstringiframeForwarded to the iframe's sandbox attribute, for DOM/CSS isolation only — not a security boundary (see the note above).
syncStylebooleanbothCopy the host document's already-compiled <link>/<style> tags in (into the iframe document, or directly into the shadow root). Can't include utility classes that only appear in code typed at runtime — see How Tailwind reaches the preview.
scriptsstring[]iframeExternal script URLs to load into the iframe document (e.g. a Tailwind runtime).
stylesstring[]iframeRaw CSS strings to inject as <style> tags into the iframe.
stylesheetsstring[]iframeExternal stylesheet URLs to <link> into the iframe.
autoHeightbooleaniframeSize the iframe to its content instead of a fixed height.
onLoaded() => voidiframeCalled once the iframe has finished its initial load.