The side panel component that displays artifact previews, code, and interactive editors. Supports preview mode, code mode, split view, fullscreen, and resizing.
Import
import { ArtifactusePanel } from 'artifactuse/vue'
import { ArtifactusePanel } from 'artifactuse/vue2'
import { ArtifactusePanel } from 'artifactuse/react'
import { ArtifactusePanel } from 'artifactuse/svelte'
Usage
<template>
<div class="app-container">
<div class="chat">
<!-- Your chat messages -->
</div>
<ArtifactusePanel
@ai-request="handleAIRequest"
@save="handleSave"
@export="handleExport"
@form-submit="handleFormSubmit"
/>
</div>
</template>
<div className="app-container">
<div className="chat">
{/* Your chat messages */}
</div>
<ArtifactusePanel
onAIRequest={handleAIRequest}
onSave={handleSave}
onExport={handleExport}
onFormSubmit={handleFormSubmit}
/>
</div>
<div class="app-container">
<div class="chat">
<!-- Your chat messages -->
</div>
<ArtifactusePanel
on:aiRequest={handleAIRequest}
on:save={handleSave}
on:export={handleExport}
on:formSubmit={handleFormSubmit}
/>
</div>
Layout
The panel should be a sibling to your chat container in a flex layout:
.app-container {
display: flex;
height: 100%;
overflow: hidden;
}
.chat {
flex: 1;
min-width: 0;
overflow-y: auto;
}
The panel automatically positions itself on the right side and is resizable.
Props
| Prop | Type | Default | Description |
|---|
panelWidth | Number | 65 | Initial panel width as a percentage (25–75). Users can still drag to resize. |
splitPosition | Number | 50 | Initial split view position as a percentage (20–80). Users can still drag to resize. |
externalPreview | Boolean | false | Show “Open in new tab” button in panel header. Only visible when a preview URL exists. |
<ArtifactusePanel
:panel-width="50"
:split-position="60"
@ai-request="handleAIRequest"
/>
<ArtifactusePanel
panelWidth={50}
splitPosition={60}
onAIRequest={handleAIRequest}
/>
<ArtifactusePanel
initialPanelWidth={50}
initialSplitPosition={60}
on:aiRequest={handleAIRequest}
/>
These values set the initial position only. Users can still drag the panel edge or split divider to resize. Values outside the valid range are clamped automatically. Props override the global config values (panelWidth and splitPosition in provideArtifactuse).
Events
| Event | Payload | Description |
|---|
ai-request | { prompt, context, requestId } | AI assistance requested from panel (e.g., “Fix this code”) |
save | { artifactId, data } | Save requested for current artifact |
export | { artifactId, blob, filename } | Export completed |
form-submit | { formId, action, values } | Panel form submitted |
edit:save | { artifactId, artifact, code } | Code saved from edit tab |
Handling AI Requests
When users request AI assistance from the panel (e.g., clicking “Fix”, “Improve”, or using the AI input), handle it like this:
<script setup>
async function handleAIRequest({ prompt, context, requestId }) {
// context contains the current artifact code/content
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [
{ role: 'system', content: 'You are a helpful coding assistant.' },
{ role: 'user', content: `${prompt}\n\nContext:\n${context}` }
]
})
// The response will be processed and update the artifact
}
</script>
<template>
<ArtifactusePanel @ai-request="handleAIRequest" />
</template>
const handleAIRequest = async ({ prompt, context, requestId }) => {
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [
{ role: 'system', content: 'You are a helpful coding assistant.' },
{ role: 'user', content: `${prompt}\n\nContext:\n${context}` }
]
})
}
<ArtifactusePanel onAIRequest={handleAIRequest} />
View Modes
The panel supports four view modes:
| Mode | Description |
|---|
preview | Live preview of the artifact (default for HTML, React, Vue) |
code | Syntax-highlighted code view (read-only, uses Prism.js) |
split | Side-by-side preview and code |
edit | Editable code editor (requires CodeMirror via editor config) |
Control view mode programmatically:
const { setViewMode } = useArtifactuse()
setViewMode('preview')
setViewMode('code')
setViewMode('split')
setViewMode('edit')
Tab Filtering
Control which tabs are visible when opening artifacts programmatically:
const { openFile } = useArtifactuse()
// Only show code and edit tabs
openFile('app.js', code, { tabs: ['code', 'edit'] })
// Only show preview and code (no split)
openFile('page.html', code, { tabs: ['preview', 'code'] })
// Update an existing artifact (no duplicate tab)
updateFile(artifact, newCode)
The edit tab only appears when CodeMirror modules are provided via the editor config option. See Code Artifacts for setup instructions.
Fullscreen
Toggle fullscreen mode:
const { toggleFullscreen } = useArtifactuse()
toggleFullscreen()
Panel Controls
The panel header includes:
- View mode tabs - Switch between preview/code/split/edit
- Save button - Appears when the edit tab is active (emits
edit:save event)
- Open in new tab button - Opens the artifact preview URL in a new browser tab (requires
externalPreview enabled and a preview URL)
- Fullscreen button - Expand to full screen
- Close button - Close the panel
The panel footer includes:
- Branding - “Powered by Artifactuse” (can be hidden with license)
- Navigation - Previous/next artifact buttons
- Actions - Copy, download, export buttons
Panel Methods
Control the panel programmatically:
const { openPanel, closePanel, togglePanel } = useArtifactuse()
openPanel() // Open panel in empty "viewer" state
closePanel() // Close panel
togglePanel() // Toggle panel open/closed
openPanel()
Opens the panel in an empty viewer state with no artifact selected. The panel displays an “Artifact Viewer” header and a prompt to open an artifact. When an artifact is subsequently opened (via openArtifact(), openFile(), or openCode()), the empty state is automatically cleared.
This is useful for showing the panel before any artifact content is ready — for example, while waiting for an AI response.
Panel Events
Listen for panel lifecycle events:
const { on } = useArtifactuse()
on('panel:opened', () => {
console.log('Panel opened')
})
on('panel:closed', () => {
console.log('Panel closed')
})
on('panel:toggled', ({ isOpen }) => {
console.log('Panel toggled:', isOpen)
})
| Event | Payload | Description |
|---|
panel:opened | — | Emitted when openPanel() is called |
panel:closed | — | Emitted when closePanel() is called or the close button is clicked |
panel:toggled | { isOpen } | Emitted when togglePanel() is called |
Artifact Navigation
When multiple artifacts exist, users can navigate between them using the footer controls or programmatically:
const { openArtifact, state } = useArtifactuse()
// Open specific artifact
openArtifact(artifact)
// Access all artifacts
const allArtifacts = state.artifacts
Multi-Tab
Enable multi-tab mode to open multiple artifacts as tabs, similar to a code editor:
provideArtifactuse({
multiTab: true,
})
When enabled:
- Clicking an artifact card or calling
openFile() / openCode() opens it in a new tab (or focuses it if already open)
- Each tab preserves its own view mode (preview, code, split, edit)
- Closing the active tab switches to the adjacent tab
- The prev/next navigation is replaced by the tab bar
- Artifacts from streamed messages do not auto-open as tabs
Tab Methods
const { closeTab, closeOtherTabs, closeAllTabs } = useArtifactuse()
// Close a specific tab
closeTab(artifactId)
// Close all tabs except one
closeOtherTabs(artifactId)
// Close all open tabs
closeAllTabs()
State
When multi-tab is active, two additional state fields are available:
| Field | Type | Description |
|---|
state.openTabs | string[] | Ordered array of open artifact IDs |
state.tabViewModes | object | Map of artifact ID to view mode per tab |
Multi-tab is opt-in and disabled by default. When multiTab: false (default), the panel behaves exactly as before with single-artifact navigation.
Mobile Behavior
On mobile devices (< 768px), the panel:
- Opens as a full-screen overlay
- Hides the resize handle
- Shows a backdrop behind the panel
- Uses vertical split in split mode
Vue 2 Portal
For Vue 2, the panel uses portal-vue for fullscreen/mobile rendering. Add the portal target:
<template>
<div class="app-container">
<div class="chat">...</div>
<ArtifactusePanel />
<!-- Required for Vue 2 -->
<portal-target name="artifactuse" />
</div>
</template>