···340340 }
341341 }
342342343343+ let sidePanelOpen = false;
344344+345345+ browser.runtime.onConnect.addListener((port) => {
346346+ if (port.name === 'sidepanel') {
347347+ sidePanelOpen = true;
348348+ port.onDisconnect.addListener(() => {
349349+ sidePanelOpen = false;
350350+ });
351351+ }
352352+ });
353353+343354 browser.commands?.onCommand.addListener((command) => {
344344- if (command === 'open-sidebar') {
355355+ if (command === 'toggle-sidebar') {
345356 const browserAny = browser as any;
346357 if (browserAny.sidePanel) {
347358 chrome.windows.getCurrent((win) => {
348359 if (win?.id) {
349349- browserAny.sidePanel.open({ windowId: win.id }).catch((err: Error) => {
350350- console.error('Could not open side panel:', err);
351351- });
360360+ if (sidePanelOpen && typeof browserAny.sidePanel.close === 'function') {
361361+ browserAny.sidePanel.close({ windowId: win.id }).catch((err: Error) => {
362362+ console.error('Could not close side panel:', err);
363363+ });
364364+ } else {
365365+ browserAny.sidePanel.open({ windowId: win.id }).catch((err: Error) => {
366366+ console.error('Could not open side panel:', err);
367367+ });
368368+ }
352369 }
353370 });
354371 } else if (browserAny.sidebarAction) {
355355- browserAny.sidebarAction.open().catch((err: Error) => {
356356- console.warn('Could not open Firefox sidebar:', err);
372372+ browserAny.sidebarAction.toggle().catch((err: Error) => {
373373+ console.warn('Could not toggle Firefox sidebar:', err);
357374 });
358375 }
359376 return;
+4
extension/src/entrypoints/sidepanel/main.tsx
···11import React from 'react';
22import ReactDOM from 'react-dom/client';
33+import { browser } from 'wxt/browser';
34import App from '@/components/sidepanel/App';
45import '@/assets/styles.css';
66+77+// Connect a port so the background script can track open/closed state
88+browser.runtime.connect({ name: 'sidepanel' });
59610ReactDOM.createRoot(document.getElementById('root')!).render(
711 <React.StrictMode>