Skip to content

shadcn.io is an independent project built on shadcn/ui

Components

Free

Sandbox for React Aria

Edit HTML, CSS and JavaScript beside a live preview and a console, in a sandboxed frame. For React with React Aria, for tutorials and live examples.

A small playground: files on one side, the page they make on the other, and a console for what its scripts log.

Use it in a tutorial or a docs page where the reader should change the code and see the result at once. It runs HTML, CSS and JavaScript, not a React or npm project: there is no bundler and no package install, so import from npm and JSX won't run. To let the reader edit code that doesn't run, use a Code Editor alone. In React, each part reads the files from SandboxProvider, so you lay them out with tabs, side by side, or both.

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.

The install also adds Code Editor, Tabs and Button.

Anatomy

Sandbox anatomy: provider, tabs list, tabs trigger, file explorer, code editor, preview
SandboxProvider
└── SandboxTabs
    ├── SandboxTabsList
    │   └── SandboxTabsTrigger
    └── SandboxTabsContent
        └── SandboxLayout
            ├── SandboxFileExplorer
            ├── SandboxCodeEditor
            ├── SandboxPreview
            └── SandboxConsole

SandboxProvider holds the files and draws the frame. The tabs are optional: put SandboxLayout straight inside the provider for a side-by-side view.

Usage

import {
  SandboxCodeEditor, SandboxLayout, SandboxPreview, SandboxProvider,
} from "@/components/ui/sandbox";
const files = {
  "/index.html": `<h1>Hello</h1>`,
  "/styles.css": `h1 { font-family: system-ui; }`,
  "/script.js": `console.log("ready")`,
};

<SandboxProvider className="h-96" defaultFiles={files}>
  <SandboxLayout>
    <SandboxCodeEditor showTabs />
    <SandboxPreview />
  </SandboxLayout>
</SandboxProvider>;

How it runs

  • One page. The preview is the first .html file. A <link> to one of the CSS files and a <script src> to one of the JavaScript files are inlined where they are; files it doesn't link are added anyway, CSS to the head and JavaScript to the end of the body.
  • A sandboxed frame. The page runs in an iframe with sandbox="allow-scripts" (plus forms and dialogs) and no same-origin access, so its scripts can't read your page, its cookies or its storage.
  • Again after each edit. The preview runs again 500 ms after typing stops (delay), with a clean console. The refresh button runs it again at once.
  • A console. Each console.log, info, warn, error and debug call, and every uncaught error, is posted from the frame to SandboxConsole; objects show as JSON.
  • Nothing to install. No bundler, no service, no network: the files are strings in your page, and only they run.

Demos

Split

A file explorer, the editor with line numbers, and the preview, side by side in one SandboxLayout. It opens on the stylesheet with defaultActiveFile, and the script fills in the heading. Use it on a wide page where the reader should see the code and the page at once. Below about 670 pixels the panes stack, and the explorer becomes a row.

Preview width

Console

A store page whose buttons log: an info line, a warning when the cart is empty, and an uncaught error from Pay. The preview and the console share a tab set beside the editor; every panel stays mounted, so the page keeps running and logging while the console is shown. Use a console when the lesson is about what a script does, not how the page looks.

Preview width

FAQ

What code can Sandbox run?

HTML, CSS and JavaScript as the browser runs them. There is no bundler, so JSX, TypeScript and bare imports such as react or lodash don't run; an import from a full URL that serves an ES module does, in a script with type module. For a React or npm project, link to a hosted playground instead. Sandbox suits lessons, snippets and demos of the web platform.

Is it safe to run code a reader typed?

The code runs in an iframe with the sandbox attribute set to allow scripts, forms and dialogs, without same-origin access. It can't read your page, its cookies, its local storage or the reader's session, and it can't navigate your page. It can still use the network like any page, so don't run code from strangers on a page that holds secrets in the URL.

How do I give Sandbox its files in React?

Pass defaultFiles, an object from path to code, such as index.html, styles.css and script.js. To keep the files yourself, pass files and update them in onFilesChange, which gets every file after each edit. defaultActiveFile picks the file the editor opens on.

Why does a script tag in my files break my component?

A closing script tag inside a string ends the script block that holds it, in an HTML file or a single-file component. You don't need one: Sandbox adds every JavaScript file the page doesn't link to the end of the body. If you do link one, write the closing tag as <\/script> in your source.

Why is my Sandbox console empty?

The console shows what the preview logs, so a SandboxPreview has to be on the page, even in a tab that's hidden. SandboxTabs keeps every panel mounted for that reason. The console is cleared each time the preview runs again, after an edit or the refresh button. Logs from another sandbox on the same page never mix in.

How do I lay out the Sandbox parts?

Put the parts you want in SandboxLayout: side by side on a wide sandbox, stacked on a narrow one. Use SandboxTabs to switch between views in the same space, as the first demo does with Code and Preview, or nest tabs in a layout, as the Console demo does. Give SandboxProvider a height; the panes fill it and scroll.

How do I install Sandbox in React?

Run the command in the Installation section on this page. It adds the Sandbox parts with Code Editor, Tabs and Button. Import the parts from your ui folder. The command uses the shadcn CLI.

API Reference

SandboxProvider

PropType
files?SandboxFiles

The files, controlled: HTML, CSS and JavaScript, by path.

defaultFiles?SandboxFiles

The files when it starts, uncontrolled.

Default
{}
onFilesChange?(files: SandboxFiles) → void

Called with every file after each edit.

Parameters

files – SandboxFiles

Returns
void
defaultActiveFile?string

The file the editor opens on. @default the first file.

Default
""
delay?number

How long the preview waits after the last edit before it runs the files again, in milliseconds.

Default
500
className?string

Merged with the part's classes.

SandboxLayout

<div> data-slot="sandbox-layout"

PropType
className?string

Merged with the part's classes.

SandboxTabs

data-slot="sandbox-tabs"

PropType
value?string

The tab shown, controlled.

defaultValue?string

The tab shown first, uncontrolled.

onValueChange?(value: string) → void

Called with the tab chosen.

Parameters

value – string

Returns
void
children?ChildrenOrFunction<T>

The children of the component. A function may be provided to alter the children based on component state.

Type
ChildrenOrFunction<T>
isDisabled?boolean

Whether the TabList is disabled. Shows that a selection exists, but is not available in that circumstance.

keyboardActivation?"automatic" | "manual"

Whether tabs are activated automatically on focus or manually.

Type
"automatic" | "manual"
Default
"automatic"
orientation?"horizontal" | "vertical"

The orientation of the tabs.

Type
"horizontal" | "vertical"
Default
"horizontal"
slot?string | null

A slot name for the component. Slots allow the component to receive props from a parent component. An explicit null value indicates that the local props completely override all props received from a parent.

Type
string | null
Default
sandbox-tabs
style?StyleOrFunction<T>

The inline [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) for the element. A function may be provided to compute the style based on component state.

Type
StyleOrFunction<T>
render?DOMRenderFunction<E, T>

Overrides the default DOM element with a custom render function. This allows rendering existing components with built-in styles and behaviors such as router links, animation libraries, and pre-styled components. Requirements: - You must render the expected element type (e.g. if <button> is expected, you cannot render an <a>). - Only a single root DOM element can be rendered (no fragments). - You must pass through props and ref to the underlying DOM element, merging with your own prop as appropriate.

Type
DOMRenderFunction<E, T>
className?string

Merged with the part's classes.

SandboxTabsList

data-slot="sandbox-tabs-list"

PropType
defaultSelectedKey?Key

The initial selected keys in the collection (uncontrolled).

isDisabled?boolean

Whether the TabList is disabled. Shows that a selection exists, but is not available in that circumstance.

onSelectionChange?(key: Key) → void

Handler that is called when the selection changes.

Parameters

key – Key

Returns
void
selectedKey?Key

The currently selected key in the collection (controlled).

variant?"default" | "line"

Ark default: default.

Type
"default" | "line"
Default
"line"
className?string

Merged with the part's classes.

SandboxTabsTrigger

data-slot="sandbox-tabs-trigger"

PropType
valuestring

The tab's value: the value of the content it shows.

children?ChildrenOrFunction<T>

The children of the component. A function may be provided to alter the children based on component state.

Type
ChildrenOrFunction<T>
isDisabled?boolean

Whether the tab is disabled.

style?StyleOrFunction<T>

The inline [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) for the element. A function may be provided to compute the style based on component state.

Type
StyleOrFunction<T>
render?(props: DetailedHTMLProps<LinkWithRequiredHref, HTMLAnchorElement> | React.JSX.IntrinsicElements[Fallback], renderProps: T) → ReactElement

Overrides the default DOM element with a custom render function. This allows rendering existing components with built-in styles and behaviors such as router links, animation libraries, and pre-styled components. Note: You can check if 'href' in props in order to tell whether to render an <a> element. Requirements: - You must render the expected element type (e.g. if <a> is expected, you cannot render a <button>). - Only a single root DOM element can be rendered (no fragments). - You must pass through props and ref to the underlying DOM element, merging with your own prop as appropriate.

Type
(props: DetailedHTMLProps<LinkWithRequiredHref, HTMLAnchorElement> | React.JSX.IntrinsicElements[Fallback], renderProps: T) → ReactElement
Parameters

props – DetailedHTMLProps<LinkWithRequiredHref

HTMLAnchorElement> | React.JSX.IntrinsicElements[Fallback]

renderProps – T

Returns
ReactElement
className?string

Merged with the part's classes.

SandboxTabsContent

data-slot="sandbox-tabs-content"

PropType
valuestring

The value of the tab that shows it.

children?ChildrenOrFunction<T>

The children of the component. A function may be provided to alter the children based on component state.

Type
ChildrenOrFunction<T>
shouldForceMount?boolean

Whether to mount the tab panel in the DOM even when it is not currently selected. Inactive tab panels are inert and cannot be interacted with. They must be styled appropriately so this is clear to the user visually.

Default
false
style?StyleOrFunction<T>

The inline [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) for the element. A function may be provided to compute the style based on component state.

Type
StyleOrFunction<T>
render?DOMRenderFunction<E, T>

Overrides the default DOM element with a custom render function. This allows rendering existing components with built-in styles and behaviors such as router links, animation libraries, and pre-styled components. Requirements: - You must render the expected element type (e.g. if <button> is expected, you cannot render an <a>). - Only a single root DOM element can be rendered (no fragments). - You must pass through props and ref to the underlying DOM element, merging with your own prop as appropriate.

Type
DOMRenderFunction<E, T>
className?string

Merged with the part's classes.

SandboxCodeEditor

<div> data-slot="sandbox-code-editor"

PropType
readOnly?boolean

The files can be read and copied, not changed.

Default
false
showLineNumbers?boolean

Number each line.

Default
false
showTabs?boolean

A tab per file above the code, to switch files.

Default
false
wrapContent?boolean

Wrap long lines instead of scrolling sideways.

Default
false
className?string

Merged with the part's classes.

SandboxFileExplorer

<nav> data-slot="sandbox-file-explorer"

PropType
className?string

Merged with the part's classes.

SandboxPreview

<div> data-slot="sandbox-preview"

PropType
showRefreshButton?boolean

A button that runs the files again. @default true.

Default
true
title?string

The frame's accessible name.

Default
"Preview"
className?string

Merged with the part's classes.

SandboxConsole

<div> data-slot="sandbox-console"

PropType
className?string

Merged with the part's classes.

AttributeType
data-level?string

Mirrors level.