feat(ui): add right-click close menu for context panel tabs (#3217)

Resolves openchamber/openchamber#3123.

The right panel's tab strip (browser, files, chat, and other
multi-instance surfaces) now supports a right-click context menu with
Close, Close others, Close to the left, Close to the right, and Close
all. These act on the current surface's tabs and reuse the new bulk
close action, so closing the active surface's last tab still closes the
panel while other surfaces remain.

- Add closeContextPanelTabs(directory, ids) to useUIStore
- Add opt-in tabContextMenu prop to SortableTabsStrip (no impact on other consumers)
- Wire the menu in ContextPanel with full i18n coverage across 11 locales
- Cover the bulk close with store tests
This commit is contained in:
Angel Davila
2026-08-29 00:35:24 +03:00
committed by GitHub
parent cbe908009b
commit a78ecf8a7c
18 changed files with 251 additions and 23 deletions
+5
View File
@@ -1115,6 +1115,11 @@ export const dict = {
'contextPanel.browser.annotate.submit': 'Anhängen',
'contextPanel.browser.trustNotice': 'Seiten, die hier geöffnet werden, laufen mit vollständigem Zugriff auf OpenChamber — erforderlich für Inspect und Screenshots. Öffnen Sie nur Seiten, denen Sie vertrauen: Eine bösartige Seite könnte Ihre Daten lesen oder in Ihrem Namen handeln.',
'contextPanel.tab.closeTabAria': '{label}-Registerkarte schließen',
'contextPanel.tab.menu.close': 'Schließen',
'contextPanel.tab.menu.closeOthers': 'Andere schließen',
'contextPanel.tab.menu.closeToLeft': 'Tabs links daneben schließen',
'contextPanel.tab.menu.closeToRight': 'Tabs rechts daneben schließen',
'contextPanel.tab.menu.closeAll': 'Alle Tabs schließen',
'contextPanel.actions.collapsePanel': 'Panel einklappen',
'contextPanel.actions.expandPanel': 'Panel ausklappen',
'contextPanel.actions.closePanel': 'Panel schließen',
+5
View File
@@ -1308,6 +1308,11 @@ export const dict = {
'contextPanel.browser.annotate.submit': 'Attach',
'contextPanel.browser.trustNotice': 'Pages opened here run with full access to OpenChamber — needed for inspect and screenshots. Only open sites you trust: a malicious page could read your data or act on your behalf.',
'contextPanel.tab.closeTabAria': 'Close {label} tab',
'contextPanel.tab.menu.close': 'Close',
'contextPanel.tab.menu.closeOthers': 'Close others',
'contextPanel.tab.menu.closeToLeft': 'Close tabs to the left',
'contextPanel.tab.menu.closeToRight': 'Close tabs to the right',
'contextPanel.tab.menu.closeAll': 'Close all tabs',
'contextPanel.actions.collapsePanel': 'Collapse panel',
'contextPanel.actions.expandPanel': 'Expand panel',
'contextPanel.actions.closePanel': 'Close panel',
+5
View File
@@ -1309,6 +1309,11 @@ export const dict: Record<I18nKey, string> = {
"contextPanel.browser.annotate.submit": "Adjuntar",
"contextPanel.browser.trustNotice": "Las páginas que abras aquí se ejecutan con acceso completo a OpenChamber: necesario para la inspección y las capturas. Abre solo sitios de confianza: una página maliciosa podría leer tus datos o actuar en tu nombre.",
"contextPanel.tab.closeTabAria": "Cerrar pestaña {label}",
"contextPanel.tab.menu.close": "Cerrar",
"contextPanel.tab.menu.closeOthers": "Cerrar otras",
"contextPanel.tab.menu.closeToLeft": "Cerrar pestañas a la izquierda",
"contextPanel.tab.menu.closeToRight": "Cerrar pestañas a la derecha",
"contextPanel.tab.menu.closeAll": "Cerrar todas las pestañas",
"contextPanel.actions.collapsePanel": "Colapsar panel",
"contextPanel.actions.expandPanel": "Expandir panel",
"contextPanel.actions.closePanel": "Cerrar panel",
+5
View File
@@ -1075,6 +1075,11 @@ export const dict = {
'contextPanel.browser.empty': 'Navigateur Internet',
'contextPanel.browser.emptyHint': 'Entrez une adresse ci-dessus pour commencer à naviguer sur le Web',
'contextPanel.tab.closeTabAria': 'Fermer l\'onglet {label}',
'contextPanel.tab.menu.close': 'Fermer',
'contextPanel.tab.menu.closeOthers': 'Fermer les autres',
'contextPanel.tab.menu.closeToLeft': 'Fermer les onglets à gauche',
'contextPanel.tab.menu.closeToRight': 'Fermer les onglets à droite',
'contextPanel.tab.menu.closeAll': 'Fermer tous les onglets',
'contextPanel.actions.collapsePanel': 'Réduire le panneau',
'contextPanel.actions.expandPanel': 'Agrandir le panneau',
'contextPanel.actions.closePanel': 'Fermer le panneau',
+5
View File
@@ -1305,6 +1305,11 @@ export const dict: Record<I18nKey, string> = {
'contextPanel.browser.annotate.submit': '添付',
'contextPanel.browser.trustNotice': 'ここで開かれたページはOpenChamberへの完全なアクセス権を持ちます — 検査とスクリーンショットに必要です。信頼できるサイトのみを開いてください: 悪意のあるページがデータを読み取ったりあなたの代わりに行動したりする可能性があります。',
'contextPanel.tab.closeTabAria': '{label}タブを閉じる',
'contextPanel.tab.menu.close': '閉じる',
'contextPanel.tab.menu.closeOthers': '他を閉じる',
'contextPanel.tab.menu.closeToLeft': '左のタブを閉じる',
'contextPanel.tab.menu.closeToRight': '右のタブを閉じる',
'contextPanel.tab.menu.closeAll': 'すべてのタブを閉じる',
'contextPanel.actions.collapsePanel': 'パネルを折りたたむ',
'contextPanel.actions.expandPanel': 'パネルを展開',
'contextPanel.actions.closePanel': 'パネルを閉じる',
+5
View File
@@ -1358,6 +1358,11 @@ export const dict: Record<I18nKey, string> = {
'chat.messageBody.actions.openPreviewAria': '미리보기 열기',
'chat.messageBody.actions.openPreview': '미리보기 열기',
'contextPanel.tab.closeTabAria': '{label} 탭 닫기',
'contextPanel.tab.menu.close': '닫기',
'contextPanel.tab.menu.closeOthers': '다른 탭 닫기',
'contextPanel.tab.menu.closeToLeft': '왼쪽 탭 닫기',
'contextPanel.tab.menu.closeToRight': '오른쪽 탭 닫기',
'contextPanel.tab.menu.closeAll': '모든 탭 닫기',
'contextPanel.actions.collapsePanel': '접기 패널',
'contextPanel.actions.expandPanel': '펼치기 패널',
'contextPanel.actions.closePanel': '패널 닫기',
+5
View File
@@ -1696,6 +1696,11 @@ export const dict: Record<I18nKey, string> = {
'contextPanel.preview.upstreamUnreachable': 'Serwer deweloperski nie odpowiada.',
'contextPanel.preview.upstreamUnreachableHint': 'Upewnij się, że serwer deweloperski nadal działa, a następnie ponów próbę.',
'contextPanel.tab.closeTabAria': 'Zamknij kartę {label}',
'contextPanel.tab.menu.close': 'Zamknij',
'contextPanel.tab.menu.closeOthers': 'Zamknij pozostałe',
'contextPanel.tab.menu.closeToLeft': 'Zamknij karty po lewej',
'contextPanel.tab.menu.closeToRight': 'Zamknij karty po prawej',
'contextPanel.tab.menu.closeAll': 'Zamknij wszystkie karty',
'contextSidebar.actions.copied': 'Skopiowano',
'contextSidebar.actions.copy': 'Kopiuj',
'contextSidebar.actions.copyJson': 'Kopiuj JSON',
@@ -1309,6 +1309,11 @@ export const dict: Record<I18nKey, string> = {
"contextPanel.browser.annotate.submit": "Anexar",
"contextPanel.browser.trustNotice": "As páginas abertas aqui são executadas com acesso total ao OpenChamber — necessário para inspeção e capturas de tela. Abra apenas sites confiáveis: uma página maliciosa pode ler seus dados ou agir em seu nome.",
"contextPanel.tab.closeTabAria": "Fechar aba {label}",
"contextPanel.tab.menu.close": "Fechar",
"contextPanel.tab.menu.closeOthers": "Fechar outras",
"contextPanel.tab.menu.closeToLeft": "Fechar abas à esquerda",
"contextPanel.tab.menu.closeToRight": "Fechar abas à direita",
"contextPanel.tab.menu.closeAll": "Fechar todas as abas",
"contextPanel.actions.collapsePanel": "Recolher painel",
"contextPanel.actions.expandPanel": "Expandir painel",
"contextPanel.actions.closePanel": "Fechar painel",
+5
View File
@@ -1284,6 +1284,11 @@ export const dict = {
'contextPanel.browser.annotate.submit': 'Ekle',
'contextPanel.browser.trustNotice': 'Burada açılan sayfalar OpenChamber\'a tam erişimle çalışır — inceleme ve ekran görüntüleri için gereklidir. Yalnızca güvendiğiniz siteleri açın: kötü niyetli bir sayfa verilerinizi okuyabilir veya sizin adınıza hareket edebilir.',
'contextPanel.tab.closeTabAria': '{label} sekmesini kapat',
'contextPanel.tab.menu.close': 'Kapat',
'contextPanel.tab.menu.closeOthers': 'Diğerlerini kapat',
'contextPanel.tab.menu.closeToLeft': 'Soldaki sekmeleri kapat',
'contextPanel.tab.menu.closeToRight': 'Sağdaki sekmeleri kapat',
'contextPanel.tab.menu.closeAll': 'Tüm sekmeleri kapat',
'contextPanel.actions.collapsePanel': 'Paneli daralt',
'contextPanel.actions.expandPanel': 'Paneli genişlet',
'contextPanel.actions.closePanel': 'Paneli kapat',
+5
View File
@@ -1309,6 +1309,11 @@ export const dict: Record<I18nKey, string> = {
"contextPanel.browser.annotate.submit": "Додати",
"contextPanel.browser.trustNotice": "Сторінки, відкриті тут, працюють із повним доступом до OpenChamber — це потрібно для inspect і скріншотів. Відкривайте лише сайти, яким довіряєте: шкідлива сторінка може прочитати ваші дані чи діяти від вашого імені.",
"contextPanel.tab.closeTabAria": "Закрити вкладку {label}",
"contextPanel.tab.menu.close": "Закрити",
"contextPanel.tab.menu.closeOthers": "Закрити інші",
"contextPanel.tab.menu.closeToLeft": "Закрити вкладки ліворуч",
"contextPanel.tab.menu.closeToRight": "Закрити вкладки праворуч",
"contextPanel.tab.menu.closeAll": "Закрити всі вкладки",
"contextPanel.actions.collapsePanel": "Згорнути панель",
"contextPanel.actions.expandPanel": "Розгорнути панель",
"contextPanel.actions.closePanel": "Закрити панель",
@@ -1309,6 +1309,11 @@ export const dict: Record<I18nKey, string> = {
'contextPanel.browser.annotate.submit': '附加',
'contextPanel.browser.trustNotice': '在此打开的页面以对 OpenChamber 的完全访问权限运行 — 检查和截图需要此权限。仅打开你信任的站点:恶意页面可能读取你的数据或以你的身份执行操作。',
'contextPanel.tab.closeTabAria': '关闭 {label} 标签',
'contextPanel.tab.menu.close': '关闭',
'contextPanel.tab.menu.closeOthers': '关闭其他',
'contextPanel.tab.menu.closeToLeft': '关闭左侧标签',
'contextPanel.tab.menu.closeToRight': '关闭右侧标签',
'contextPanel.tab.menu.closeAll': '关闭所有标签',
'contextPanel.actions.collapsePanel': '折叠面板',
'contextPanel.actions.expandPanel': '展开面板',
'contextPanel.actions.closePanel': '关闭面板',
@@ -1321,6 +1321,11 @@ export const dict: Record<I18nKey, string> = {
'contextPanel.browser.annotate.submit': '附加',
'contextPanel.browser.trustNotice': '在此開啟的頁面以對 OpenChamber 的完整存取權限執行 — 檢查與截圖需要此權限。僅開啟你信任的網站:惡意頁面可能讀取你的資料或以你的身分執行操作。',
'contextPanel.tab.closeTabAria': '關閉 {label} 分頁',
'contextPanel.tab.menu.close': '關閉',
'contextPanel.tab.menu.closeOthers': '關閉其他',
'contextPanel.tab.menu.closeToLeft': '關閉左側分頁',
'contextPanel.tab.menu.closeToRight': '關閉右側分頁',
'contextPanel.tab.menu.closeAll': '關閉所有分頁',
'contextPanel.actions.collapsePanel': '摺疊面板',
'contextPanel.actions.expandPanel': '展開面板',
'contextPanel.actions.closePanel': '關閉面板',