Which API each browser uses
Firefox does not have
chrome.sidePanel, and Chrome does not have sidebarAction. Safari has neither. See Building Safari extensions for the guard that keeps a Safari background alive.
Declare the panel in the manifest
Use browser prefixes so that each build gets its own key:manifest.json
dist/. The available browsers page lists the targets that each prefix reaches.
Three rules apply to this manifest:
- Chrome needs the
sidePanelpermission. Without it, Chrome shows no panel. The build does not add it for aside_panelkey that you wrote. - A prefixed key replaces the plain key. If you also write a plain
permissionslist,chromium:permissionsreplaces it on Chromium builds. Put every Chromium permission inchromium:permissions. - One key alone still gives Firefox a sidebar. With Extension.js 4.1.33, a manifest that declares only
side_panelbuilds for Firefox with asidebar_actionkey that points at the same page. The build prints a warning when it does this. Declare both keys to control each browser yourself.
Runtime API: chrome.sidePanel vs browser.sidebarAction
Notes on the table:
sidePanel.close()exists from Chrome 141. It does nothing when the panel is already closed. From Chrome 145,close({ tabId })rejects when only the global panel is open. Before Chrome 145, the same call closed the global panel.- Chrome has no
isOpen(). To know the state, listen toonOpenedandonClosed. - Firefox
setPanel,setTitle, andsetIconfail if you pass bothtabIdandwindowId. Pass one, or pass neither to change the global value. - Chrome has no title or icon API for the panel. Chrome shows the extension icon in the side panel menu.
chrome.action.setTitleandchrome.action.setIconchange the toolbar button only.
sidePanel reference and the MDN sidebarAction reference.
User gesture rules
Both browsers open a panel only when the user does something. The rules are not the same:- Firefox:
open(),close(), andtoggle()work only inside the handler for a user action. A toolbar click, a context menu item, a keyboard command, and a button on an extension page all count. - Chromium:
open()works only after a user gesture. A toolbar click, a keyboard command, a context menu item, and a click on an extension page or in a content script all count.close()has no gesture rule in the Chrome reference. - The toolbar click is the exception on Chromium. Call
setPanelBehavioronce, at the top level of the background script. After that, a toolbar click opens the panel and your code does not run.
Open the panel from the toolbar button
This background script gives each browser its own path. The check runs at build time, so each bundle keeps only its own half:background.js
setPanelBehavior at the top level, not inside a click handler. The behavior applies to the next clicks only, so a call from inside the first click leaves that first click with no panel.
The Firefox half uses browserAction because the manifest above builds Firefox as Manifest V2. See environment variables for the value of EXTENSION_PUBLIC_BROWSER on each target.
Open the panel from your own gesture
To open the panel from a context menu, a button, or a shortcut, test for the API at runtime. Branch onsidebarAction.open, the method that you call, and not on the browser object alone:
background.js
contextMenus to both permission lists:
manifest.json
openPanel calls open() with no await before it, so the gesture from the menu click is still valid.
Firefox builds warn about chrome.sidePanel
From 4.1.18, a production build for Firefox warns when the bundle readschrome.sidePanel. The build still succeeds. The runtime check in the previous section triggers this warning, because the Firefox bundle still contains the chrome.sidePanel.open call. The isFirefoxLike check from the toolbar sample does not trigger it, because the build removes the Chromium half. See Firefox builds warn about Chromium-only APIs for the full message and the fix.
To clear the warning in the context menu sample, replace the runtime check in openPanel with isFirefoxLike.
Next steps
- HTML entrypoints, where the side panel page is one surface.
- Background scripts, where the open logic runs.
- Permissions and host permissions.
- Cross-browser compatibility.

