Side Panel API Reference
Documentation of Chrome's
chrome.sidePanelAPI for the PraisonAI Browser Agent extension.
Availability
- Chrome 114+ for basic Side Panel
- Chrome 116+ for
sidePanel.open()programmatic opening - Chrome 140+ for
getLayout()andSidetype - Chrome 141+ for
onOpenedevent - Chrome 144+ for
onClosedevent
Permissions
{
"permissions": ["sidePanel"]
}
Manifest Configuration
{
"side_panel": {
"default_path": "sidepanel.html"
}
}
Methods
setPanelBehavior(behavior)
Configure whether clicking the action icon opens the side panel.
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true });
getPanelBehavior()
Get current panel behavior configuration.
const { openPanelOnActionClick } = await chrome.sidePanel.getPanelBehavior();
setOptions(options)
Configure side panel for specific tabs or globally.
// Global panel
await chrome.sidePanel.setOptions({ path: 'sidepanel.html' });
// Tab-specific panel
await chrome.sidePanel.setOptions({
tabId: 123,
path: 'tab-sidepanel.html',
enabled: true
});
// Disable for specific tab
await chrome.sidePanel.setOptions({
tabId: 123,
enabled: false
});
getOptions(options)
Get current panel options.
const { path, enabled } = await chrome.sidePanel.getOptions({ tabId: 123 });
open(options) — Chrome 116+
Programmatically open the side panel. Must be called in response to user action.
// Open for entire window
await chrome.sidePanel.open({ windowId: tab.windowId });
// Open for specific tab
await chrome.sidePanel.open({ tabId: tab.id });
close(options) — Chrome 141+
Close the side panel.
// Close for specific tab
await chrome.sidePanel.close({ tabId: 123 });
// Close for window
await chrome.sidePanel.close({ windowId: 456 });
getLayout() — Chrome 140+
Get the panel's current layout (left or right side).
const { side } = await chrome.sidePanel.getLayout();
// side: "left" | "right"
Events
onOpened — Chrome 141+
Fired when the side panel is opened.
chrome.sidePanel.onOpened.addListener((info) => {
console.log('Panel opened:', info.path, info.windowId, info.tabId);
});
onClosed — Chrome 144+
Fired when the side panel is closed.
chrome.sidePanel.onClosed.addListener((info) => {
console.log('Panel closed:', info.path, info.windowId, info.tabId);
});
Types
PanelBehavior
interface PanelBehavior {
openPanelOnActionClick?: boolean;
}
PanelOptions
interface PanelOptions {
tabId?: number; // Apply to specific tab (optional)
path?: string; // HTML file path
enabled?: boolean; // Enable/disable panel
}
OpenOptions
interface OpenOptions {
tabId?: number; // Open for specific tab
windowId?: number; // Open for entire window
}
CloseOptions — Chrome 141+
interface CloseOptions {
tabId?: number;
windowId?: number;
}
Side — Chrome 140+
type Side = "left" | "right";
Common Patterns
1. Global Side Panel (All Sites)
// manifest.json
{
"side_panel": { "default_path": "sidepanel.html" },
"permissions": ["sidePanel"]
}
// service-worker.js
chrome.runtime.onInstalled.addListener(() => {
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true });
});
2. Site-Specific Side Panel
const ALLOWED_ORIGIN = 'https://example.com';
chrome.tabs.onUpdated.addListener(async (tabId, info, tab) => {
if (!tab.url) return;
const url = new URL(tab.url);
await chrome.sidePanel.setOptions({
tabId,
path: 'sidepanel.html',
enabled: url.origin === ALLOWED_ORIGIN
});
});
3. Multiple Side Panels
const welcomePage = 'sidepanels/welcome.html';
const mainPage = 'sidepanels/main.html';
chrome.tabs.onActivated.addListener(async ({ tabId }) => {
const { path } = await chrome.sidePanel.getOptions({ tabId });
if (path === welcomePage) {
await chrome.sidePanel.setOptions({ path: mainPage });
}
});
4. Open from Content Script
// content-script.js
button.addEventListener('click', () => {
chrome.runtime.sendMessage({ type: 'open_side_panel' });
});
// service-worker.js
chrome.runtime.onMessage.addListener((message, sender) => {
if (message.type === 'open_side_panel') {
chrome.sidePanel.open({ tabId: sender.tab.id });
}
});
5. Context Menu Integration
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
id: 'openSidePanel',
title: 'Open side panel',
contexts: ['all']
});
});
chrome.contextMenus.onClicked.addListener((info, tab) => {
if (info.menuItemId === 'openSidePanel') {
chrome.sidePanel.open({ windowId: tab.windowId });
}
});
Best Practices
- User Gesture Required:
sidePanel.open()must be called in response to user action - Tab vs Window: Use
tabIdfor tab-specific panels,windowIdfor global - Error Handling: Always use
.catch()for async operations - Performance: Side panels have full access to Chrome APIs but share resources
- Persistence: Side panel remains open when navigating between tabs (unless disabled)