···340 }
341 }
34200000000000343 browser.commands?.onCommand.addListener((command) => {
344- if (command === 'open-sidebar') {
345 const browserAny = browser as any;
346 if (browserAny.sidePanel) {
347 chrome.windows.getCurrent((win) => {
348 if (win?.id) {
349- browserAny.sidePanel.open({ windowId: win.id }).catch((err: Error) => {
350- console.error('Could not open side panel:', err);
351- });
000000352 }
353 });
354 } else if (browserAny.sidebarAction) {
355- browserAny.sidebarAction.open().catch((err: Error) => {
356- console.warn('Could not open Firefox sidebar:', err);
357 });
358 }
359 return;
···340 }
341 }
342343+ let sidePanelOpen = false;
344+345+ browser.runtime.onConnect.addListener((port) => {
346+ if (port.name === 'sidepanel') {
347+ sidePanelOpen = true;
348+ port.onDisconnect.addListener(() => {
349+ sidePanelOpen = false;
350+ });
351+ }
352+ });
353+354 browser.commands?.onCommand.addListener((command) => {
355+ if (command === 'toggle-sidebar') {
356 const browserAny = browser as any;
357 if (browserAny.sidePanel) {
358 chrome.windows.getCurrent((win) => {
359 if (win?.id) {
360+ if (sidePanelOpen && typeof browserAny.sidePanel.close === 'function') {
361+ browserAny.sidePanel.close({ windowId: win.id }).catch((err: Error) => {
362+ console.error('Could not close side panel:', err);
363+ });
364+ } else {
365+ browserAny.sidePanel.open({ windowId: win.id }).catch((err: Error) => {
366+ console.error('Could not open side panel:', err);
367+ });
368+ }
369 }
370 });
371 } else if (browserAny.sidebarAction) {
372+ browserAny.sidebarAction.toggle().catch((err: Error) => {
373+ console.warn('Could not toggle Firefox sidebar:', err);
374 });
375 }
376 return;
+4
extension/src/entrypoints/sidepanel/main.tsx
···1import React from 'react';
2import ReactDOM from 'react-dom/client';
03import App from '@/components/sidepanel/App';
4import '@/assets/styles.css';
00056ReactDOM.createRoot(document.getElementById('root')!).render(
7 <React.StrictMode>
···1import React from 'react';
2import ReactDOM from 'react-dom/client';
3+import { browser } from 'wxt/browser';
4import App from '@/components/sidepanel/App';
5import '@/assets/styles.css';
6+7+// Connect a port so the background script can track open/closed state
8+browser.runtime.connect({ name: 'sidepanel' });
910ReactDOM.createRoot(document.getElementById('root')!).render(
11 <React.StrictMode>