Adding Items to the Action Icon Menu
Put useful commands in the right-click menu of an MV3 extension's toolbar icon: the action context, Chrome's six-item limit, toggles, quick links to options, per-tab state, and when to use it instead of the popup.
Table of Contents
- What the action context offers
- Step-by-step: a useful action menu
- Common mistakes
- Cross-browser variation
- Verification
- FAQ
- Do action menu clicks grant activeTab?
- Can items appear only on certain sites?
- Does the menu work in the extensions puzzle menu?
- What happens to the items if the extension has no popup?
- Can I localise the item titles?
- Does the action menu work when the extension is unpinned?
- Can I use separators in the action menu?
- Related
Right-clicking an extension’s toolbar icon shows the browser’s own entries — Options, Remove, Manage — and below them, whatever the extension adds with the action context. Most extensions add nothing, wasting a surface users already reach for when they want a quick command without opening the popup: pause on this site, open the dashboard, toggle a mode, report a problem. The action menu is small and constrained — Chrome shows only a handful of top-level items — but for two or three well-chosen commands it is the fastest UI the extension has. This guide shows how to use it. It belongs to context menus and right-click actions.
What the action context offers
Items created with contexts: ["action"] appear in the menu shown when the user right-clicks the extension’s toolbar icon (and in the extensions menu entry for it). Clicks fire contextMenus.onClicked with the active tab, just like page context menus, and grant activeTab for that tab. Chrome limits the number of top-level items an extension can add to this menu — chrome.contextMenus.ACTION_MENU_TOP_LEVEL_LIMIT is 6 — and items beyond the limit are ignored. Nested items under a parent are allowed. The menu is available whether the action has a popup or not, which makes it a useful complement to a popup: the popup for rich UI, the action menu for one-click commands.
Step-by-step: a useful action menu
1. Choose two to four commands
1action-menu.md
21. Pause on this site (toggle, per site) — most frequent quick action
32. Open dashboard (opens library tab)
43. Keyboard shortcuts… (opens chrome://extensions/shortcuts)
54. Report a problem (opens support form with version prefilled)
Execution context: a design note. The best candidates are commands users want without opening any UI, and destinations that are otherwise buried. Avoid duplicating everything in the popup; the action menu should feel like a shortcut list, not a second interface. The browser already provides “Options”, so a separate options item is usually redundant.
2. Create the items with the action context
1// sw.js
2chrome.runtime.onInstalled.addListener(createActionMenu);
3chrome.runtime.onStartup.addListener(createActionMenu);
4
5async function createActionMenu() {
6 await chrome.contextMenus.removeAll();
7 const items = [
8 { id: "pause-site", title: "Pause on this site", type: "checkbox", checked: false },
9 { id: "dashboard", title: "Open dashboard" },
10 { id: "shortcuts", title: "Keyboard shortcuts…" },
11 { id: "report", title: "Report a problem…" },
12 ];
13 for (const item of items.slice(0, chrome.contextMenus.ACTION_MENU_TOP_LEVEL_LIMIT)) {
14 chrome.contextMenus.create({ ...item, contexts: ["action"] });
15 }
16}
Execution context: the service worker. Slicing to the platform limit makes the code safe if the list grows. If page-context items exist too, create them in the same function — removeAll clears every item the extension owns. Items with contexts: ["action"] appear only on the toolbar icon, never in page menus.
3. Handle clicks with the active tab
1chrome.contextMenus.onClicked.addListener(async (info, tab) => {
2 switch (info.menuItemId) {
3 case "pause-site":
4 if (tab?.url) await setSiteOverride(siteKey(tab.url), { enabled: !info.checked });
5 return;
6 case "dashboard":
7 return openOrFocus(chrome.runtime.getURL("library.html"));
8 case "shortcuts":
9 return chrome.tabs.create({ url: "chrome://extensions/shortcuts" });
10 case "report": {
11 const v = chrome.runtime.getManifest().version;
12 return chrome.tabs.create({ url: `https://readable.example/support?v=${v}&b=${encodeURIComponent(navigator.userAgent)}` });
13 }
14 }
15});
Execution context: the service worker. The click grants activeTab for the tab the icon belongs to, so the handler can read tab.url and act on it without host permissions. Extensions can open chrome://extensions/shortcuts with tabs.create — the most reliable way to send users to rebind shortcuts. Prefilling the support URL with the version saves a round of questions.
4. Keep the toggle in sync with the active tab
1chrome.tabs.onActivated.addListener(async ({ tabId }) => updatePauseItem(await chrome.tabs.get(tabId)));
2chrome.tabs.onUpdated.addListener((id, change, tab) => { if (change.url && tab.active) updatePauseItem(tab); });
3
4async function updatePauseItem(tab) {
5 const paused = tab?.url ? !(await effectiveSettings(tab.url)).enabled : false;
6 chrome.contextMenus.update("pause-site", { checked: paused, enabled: Boolean(tab?.url?.startsWith("http")) });
7}
Execution context: the service worker. Checked state is global, so a per-site toggle must follow the active tab, as described in checkbox context menu items that reflect state. Disabling the item on browser pages avoids a toggle that cannot do anything.
5. Group extra items under a parent
1chrome.contextMenus.create({ id: "more", title: "More", contexts: ["action"] });
2chrome.contextMenus.create({ id: "export", parentId: "more", title: "Export library…", contexts: ["action"] });
3chrome.contextMenus.create({ id: "import", parentId: "more", title: "Import…", contexts: ["action"] });
Execution context: the service worker. Child items do not count against the top-level limit. A “More” submenu keeps the top level short while keeping less frequent commands reachable. Do not nest deeply — one level is plenty.
6. Signal state on the icon too
When the action menu toggles a mode (paused, focus mode), reflect it on the icon with a per-tab badge or title so the user can see the state without opening the menu. See setting the action title and tooltip.
7. Mention the menu once
Users rarely discover right-click menus on toolbar icons. A single line in onboarding — “Right-click the Readable icon for quick actions” — or in the popup footer is enough to make the surface useful.
Common mistakes
- More than six top-level items. Extras are dropped; use a submenu.
- Duplicating the browser’s Options entry. Redundant clutter.
- Global toggles that look per-site. Follow the active tab or label clearly.
- Commands that need confirmation. Destructive actions belong in UI with confirmation.
- No discoverability. Tell users the menu exists.
Cross-browser variation
- Chrome / Edge:
actioncontext withACTION_MENU_TOP_LEVEL_LIMITof 6. - Firefox: supports the
actioncontext (browser_actionin MV2), withonShownto update items as the menu opens and support for item icons. - Safari: support for action-icon menus is limited; test, and fall back to the popup for these commands.
Verification
- Right-click the toolbar icon and confirm the items appear below the browser’s own entries.
- Use “Pause on this site”, switch tabs and back, and confirm the checkbox reflects each site.
- Add a seventh top-level item in a test build and confirm it does not appear.
- Confirm “Keyboard shortcuts…” opens the browser’s shortcut page.
FAQ
Do action menu clicks grant activeTab?
Yes, for the tab the icon is shown for.
Can items appear only on certain sites?
Use documentUrlPatterns or toggle visible from tab events. In Firefox, onShown can hide items as the menu opens.
Does the menu work in the extensions puzzle menu?
Yes — the same items appear when the user opens the extension’s menu from the extensions puzzle menu.
What happens to the items if the extension has no popup?
Nothing changes: the action menu works the same way. Without a popup, left-click fires action.onClicked, which pairs well with an action menu — left-click performs the main action, right-click offers the alternatives.
Can I localise the item titles?
Yes. Pass chrome.i18n.getMessage("menu_pause") as the title when creating the items, and recreate them on startup so a changed browser language takes effect. Keep translated titles short; long titles are truncated in the narrow toolbar menu.
Does the action menu work when the extension is unpinned?
Yes. Users reach it from the extensions puzzle menu by opening the extension’s entry, where the same items appear.
Can I use separators in the action menu?
Yes. A type: "separator" item groups related commands, but it counts toward the top-level limit, so use one at most.
Related
- Nested and radio context menu items — submenus and choices.
- Context menu contexts and target filters — the action context among others.
- Letting users rebind extension shortcuts — where the shortcuts item leads.
- Context menus and right-click actions — the parent topic.