sidePanel Permission

8 min read

sidePanel Permission

Overview

The sidePanel API provides a persistent UI alongside web content, allowing users to view additional information or tools without leaving the current page.

API Methods

chrome.sidePanel.setOptions(options)

Configures the side panel for a specific tab or globally.

interface SetOptionsParams {
  tabId?: number;    // Optional: target specific tab
  path?: string;    // HTML file path relative to extension root
  enabled?: boolean; // Enable or disable the panel
}

Example:

// Set global default panel
await chrome.sidePanel.setOptions({
  path: 'sidepanel.html',
  enabled: true
});

// Set panel for specific tab
await chrome.sidePanel.setOptions({
  tabId: 123,
  path: 'tab-specific.html',
  enabled: true
});

chrome.sidePanel.getOptions(options)

Retrieves the current panel configuration.

interface GetOptionsParams {
  tabId?: number; // Optional: get config for specific tab
}

// Returns: { path?: string; enabled?: boolean }
const options = await chrome.sidePanel.getOptions({ tabId: 123 });

chrome.sidePanel.open(options)

Programmatically opens the side panel. Requires user gesture context.

interface OpenParams {
  tabId?: number;     // Optional: open in specific tab
  windowId?: number;  // Optional: open in specific window
}

Example:

// Open panel when action is clicked
chrome.action.onClicked.addListener(async (tab) => {
  await chrome.sidePanel.open({ tabId: tab.id });
});

// Open in current window
await chrome.sidePanel.open({ windowId: chrome.windows.WINDOW_ID_CURRENT });

Note: Available in Chrome 116+. Must be called from user gesture context (e.g., action click, keyboard shortcut).

chrome.sidePanel.setPanelBehavior(behavior)

Configures whether clicking the extension action opens the side panel.

interface PanelBehavior {
  openPanelOnActionClick: boolean;
}

Example:

// Open panel when toolbar icon is clicked
await chrome.sidePanel.setPanelBehavior({
  openPanelOnActionClick: true
});

chrome.sidePanel.getPanelBehavior()

Retrieves the current panel behavior configuration.

const behavior = await chrome.sidePanel.getPanelBehavior();
// Returns: { openPanelOnActionClick: boolean }

Manifest Declaration

{
  "permissions": ["sidePanel"],
  "side_panel": {
    "default_path": "sidepanel.html"
  }
}

The side_panel key in the manifest specifies the default HTML file to display when the side panel is opened.

Per-Tab vs Global Panel

Global Panel

Set the panel path without a tabId to apply the same panel across all tabs:

await chrome.sidePanel.setOptions({
  path: 'global-panel.html',
  enabled: true
});

Per-Tab Panel

Set a specific panel for a particular tab using tabId:

await chrome.sidePanel.setOptions({
  tabId: targetTab.id,
  path: 'custom-panel.html',
  enabled: true
});

Precedence

Per-tab configuration takes precedence over global configuration when set. A per-tab panel can be disabled by setting enabled: false while keeping the global panel active.

// Disable panel for specific tab while global panel is enabled
await chrome.sidePanel.setOptions({
  tabId: tabToDisable.id,
  enabled: false
});

Communication

The side panel does not have dedicated events. Use Chrome’s runtime messaging for communication between the side panel and service worker:

// In service worker
chrome.runtime.sendMessage({ type: 'UPDATE_DATA', payload: { ... } });

// In side panel
chrome.runtime.onMessage.addListener((message) => {
  if (message.type === 'UPDATE_DATA') {
    // Update UI
  }
});

The side panel has full access to chrome.* APIs, similar to a popup. For structured communication, consider using @theluckystrike/webext-messaging.

Use Cases

Code Examples

Basic Side Panel Setup

manifest.json:

{
  "name": "My Side Panel Extension",
  "version": "1.0",
  "manifest_version": 3,
  "permissions": ["sidePanel"],
  "side_panel": {
    "default_path": "sidepanel.html"
  },
  "action": {
    "default_title": "Open Side Panel"
  }
}

sidepanel.html:

<!DOCTYPE html>
<html>
<head>
  <style>
    body { padding: 16px; font-family: system-ui; }
  </style>
</head>
<body>
  <h1>My Side Panel</h1>
  <div id="content">Welcome!</div>
</body>
</html>

background.js:

// Enable panel on action click
await chrome.sidePanel.setPanelBehavior({
  openPanelOnActionClick: true
});

Per-Tab Panel Switching

// Switch panel based on page content
chrome.tabs.onActivated.addListener(async ({ tabId }) => {
  const tab = await chrome.tabs.get(tabId);
  
  if (tab.url?.includes('github.com')) {
    await chrome.sidePanel.setOptions({
      tabId,
      path: 'panels/github.html',
      enabled: true
    });
  } else if (tab.url?.includes('youtube.com')) {
    await chrome.sidePanel.setOptions({
      tabId,
      path: 'panels/video-tools.html',
      enabled: true
    });
  } else {
    await chrome.sidePanel.setOptions({
      tabId,
      path: 'default-panel.html',
      enabled: true
    });
  }
});

Opening Panel on Action Click

chrome.action.onClicked.addListener(async (tab) => {
  // First ensure the panel is configured
  await chrome.sidePanel.setOptions({
    path: 'panel.html',
    enabled: true
  });
  
  // Then open it
  await chrome.sidePanel.open({ tabId: tab.id });
});

Messaging Between Side Panel and Service Worker

Service Worker (background.js):

// Listen for messages from side panel
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === 'GET_PAGE_INFO') {
    chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
      const activeTab = tabs[0];
      sendResponse({ 
        title: activeTab.title, 
        url: activeTab.url 
      });
    });
    return true; // Keep message channel open for async response
  }
});

Side Panel (sidepanel.js):

// Request page info from service worker
async function getPageInfo() {
  const response = await chrome.runtime.sendMessage({ 
    type: 'GET_PAGE_INFO' 
  });
  document.getElementById('page-title').textContent = response.title;
}

document.getElementById('refresh').addEventListener('click', getPageInfo);

Cross-References

Frequently Asked Questions

How do I add a side panel to Chrome?

Declare “side_panel” in your manifest and use chrome.sidePanel.setOptions() to configure its behavior. Users access it via the toolbar icon.

Can side panels work on all pages?

Yes, you can configure side panels to show on specific URL patterns or allow users to toggle it on any page. —

Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.

No previous article
No next article