Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sidePanel API: sidePanel.close() and sidePanel.toggle() #521

Open
fregante opened this issue Jan 12, 2024 · 3 comments
Open

sidePanel API: sidePanel.close() and sidePanel.toggle() #521

fregante opened this issue Jan 12, 2024 · 3 comments
Labels
enhancement Enhancement or change to an existing feature

Comments

@fregante
Copy link

fregante commented Jan 12, 2024

The sidePanel can be opened via chrome.sidePanel.open() but the API isn't symmetrical, there is no .close() API.

It would also be useful (maybe even more so) to just .toggle() the sidebar instead, using any trigger other than the action click, for example:

  • menus.onClick
  • any <button> added on the page
  • keyboard shortcuts
  • command palettes in the content script

Alternative to chrome.sidePanel.close() (✅ it works)

As @dotproto pointed out, the sidebar can close itself via window.close(), so in other contexts you would have to set up messaging.

// background.js
function open () {
  chrome.sidePanel.open()
}
function close() {
  chrome.runtime.sendMessage('closeSidePanel');
}
// sidepanel.js
chrome.runtime.onMessage.addListener(message => {
  // Might not be as easy if there are multiple side panels open
  if (message === 'closeSidePanel') {
    window.close();
  }
})

You can also use chrome.sidePanel.setOptions({enabled: false}) but that has undesired side effects (it removes it from the side panels list)

Alternative to chrome.sidePanel.toggle() (⛔️ it doesn't work)

This is more complicated because there's no easy way to determine whether the sidebar is open, so you'd have to add another listener and hope that this delay won't cause you to lose the user gesture permission:

Warning

I just tested this and it doesn't work: Error: sidePanel.open() may only be called in response to a user gesture

function isSidePanelOpen() {
  try {
    return await chrome.runtime.sendMessage('isSidePanelOpen');
  } catch {
    return false
  }
}
async function toggle() {
  if (await isSidePanelOpen()) {
    chrome.runtime.sendMessage('closeSidePanel');
  } else {
    chrome.sidePanel.open()
  }
}
// sidepanel.js
chrome.runtime.onMessage.addListener(message => {
  // Might not be as easy if there are multiple side panels open
  if (message === 'isSidePanelOpen') {
    return true
  }

  if (message === 'closeSidePanel') {
    window.close();
  }
})
@sublimator
Copy link
Member

The sidePanel api is a bit weird really!
It's actually complicated to even react to the damn action icon on-click handler to toggle the sidebar. I've switched to using openPanelOnContextMenuClick, but it's not as versatile.
But you can trigger it on ANY keyboard event??
What's the point

@Mr-haili
Copy link

Mr-haili commented Dec 24, 2024

Hello @fregante, thank you for your solution.

Based on your solution, I think I've found a simpler way to implement the side panel toggle control.
Here's a simple trick. 😁

type OpenOptions = {
  tabId: number;
  windowId?: number;
};

const openSidePanel = async (payload: OpenOptions): Promise<void> => {
  await chrome.sidePanel.open(payload);
};

const closeSidePanel = async () => {
  // NOTE:  don't pass the tabId, or this call may not work.
  await chrome.sidePanel.setOptions({ enabled: false });
  await chrome.sidePanel.setOptions({ enabled: true });
};

@fregante
Copy link
Author

fregante commented Dec 27, 2024

@Mr-haili Note that if you do use tabId when opening, closeSidePanel will close the sidePanel in every tab.


My toggle function currently looks something like this:

function toggle () {
  chrome.sidePanel.open()
  chrome.runtime.sendMessage('closeSidePanel')
}
  • if the sidebar is open:
    • chrome.sidePanel.open will do nothing
    • the "close" message will reach it to close it
  • if the sidebar is closed
    • chrome.sidePanel.open will open it
    • the message will fail to reach the sidebar because it does not open that quickly

This is not ideal because it's the definition of a race condition.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Enhancement or change to an existing feature
Projects
None yet
Development

No branches or pull requests

4 participants