Live code sandbox components for Svelte 5 with live preview in a sandboxed iframe and auto-resolved bare imports via esm.sh.
npm i @sveltecraft/sandbox
An interactive HTML/CSS/JS sandbox with editable source panels and live preview:
<script lang="ts">
import { WebSandbox } from '@sveltecraft/sandbox';
</script>
<WebSandbox
width={800}
height={400}
code={{
html: '<button>Clicks: 0</button>',
css: `
body {
display: grid;
place-content: center;
}
button {
padding: 1rem 2rem;
font-size: 1.25rem;
cursor: pointer;
}
`,
script: `
import confetti from 'canvas-confetti';
let count = 0;
document.querySelector('button').addEventListener('click', (e) => {
count++;
e.target.textContent = \`Clicks: \${count}\`;
confetti();
});
`
}}
/>
| Prop | Type | Default | Description |
|---|---|---|---|
code |
{ html?, css?, script? } |
โ | Source code for each panel |
width |
string or number |
'100%' |
Sandbox width (number = px) |
height |
string or number |
'100%' |
Sandbox height (number = px) |
theme |
Theme |
โ | Container colors and fonts |
editorTheme |
EditorTheme |
โ | Editor syntax highlighting colors |
previewOnly |
boolean |
false |
Hide the editor, show only the preview |
classes |
string |
'' |
Additional CSS classes on the container |
A multi-file Svelte playground with dynamic file tabs and live preview:
<script lang="ts">
import { SvelteSandbox } from '@sveltecraft/sandbox';
import { files } from '$lib/examples';
</script>
<SvelteSandbox width={800} height={400} {files} />
export const files = {
'App.svelte': `
<script>
import Button from './Button.svelte';
let count = $state(0);
</script>
<Button onclick={() => count++}>
Clicks: {count}
</Button>
<style>
:global {
body {
display: grid;
place-content: center;
}
}
</style>
`,
'Button.svelte': `
<script>
let { children, onclick } = $props();
</script>
<button {onclick}>
{@render children?.()}
</button>
<style>
button {
padding: 1rem 2rem;
font-size: 1.25rem;
cursor: pointer;
}
</style>
`
};
Note: Inline template literals with
</script>or</style>won't work directly in a.sveltefile because the parser closes the tag early. Define your files in a.tsfile and import them, or use string concatenation (</scr+ipt>).
| Prop | Type | Default | Description |
|---|---|---|---|
files |
Record<string, string> |
โ | Map of filename โ source code |
entry |
string |
'App.svelte' |
Entry file to mount |
width |
string or number |
'100%' |
Sandbox width (number = px) |
height |
string or number |
'100%' |
Sandbox height (number = px) |
theme |
Theme |
โ | Container colors and fonts |
editorTheme |
EditorTheme |
โ | Editor syntax highlighting colors |
previewOnly |
boolean |
false |
Hide the editor, show only the preview |
classes |
string |
'' |
Additional CSS classes on the container |
The underlying CodeMirror 6 editor is also exported if you want to use it standalone:
<script lang="ts">
import { CodeEditor } from '@sveltecraft/sandbox';
</script>
<CodeEditor bind:value={myCode} language="javascript" theme={editorTheme} />
theme)| Prop | Default | Description |
|---|---|---|
bg |
#1b1e27 |
Background color |
border |
#29303d |
Border color |
accent |
#52ffeb |
Accent color (active tab underline) |
text |
#e4f0fb |
Text color |
textMuted |
#c2c7d6 |
Muted text color (inactive tabs) |
tabFontSize |
1rem |
Tab button font size |
radius |
0.5rem |
Border radius |
borderW |
1px |
Border width |
fontFamily |
'Atkinson Hyperlegible', sans-serif |
Container font family |
fontSize |
1rem |
Container font size |
editorTheme)| Prop | Default | Description |
|---|---|---|
accent |
#5de4c7 |
Keywords, strings, numbers, tag names |
function |
#add7ff |
Function/variable names, class names |
variable |
#e4f0fb |
Variable names, property names |
muted |
#a6accd |
Type names, punctuation, operators, attributes |
comment |
#767c9d |
Comments |
special |
#d0679d |
Booleans, null |
text |
#fff |
Editor text color |
gutter |
#767c9d |
Line number color |
fontSize |
14px |
Editor font size |
fontFamily |
'JetBrains Mono' |
Editor font family |
<WebSandbox
code={{ html: '<h1>Hello</h1>' }}
theme={{
bg: '#0f172a',
accent: '#38bdf8',
radius: '0.75rem'
}}
editorTheme={{
accent: '#38bdf8',
function: '#f472b6',
comment: '#64748b'
}}
/>
srcdoc attribute with only allow-scripts.canvas-confetti) are automatically detected and mapped to esm.sh via a <script type="importmap"> injected into the iframe.SvelteSandbox, components are compiled client-side inside the iframe with support for multi-file imports.dedent utility strips it so you can write clean, indented code blocks without affecting the output.# Start the preview app
pnpm dev
# Build the library
pnpm build
# Package for publishing
pnpm prepack
# Publish to npm
pnpm publish