From 45f1d6434ca72a762b253d98aede049966a82f96 Mon Sep 17 00:00:00 2001 From: TeaCoder52 Date: Thu, 5 Feb 2026 08:19:46 +0300 Subject: [PATCH 1/2] feat(explorer): add context menu for tabs --- .github/scripts/telegram-notify.js | 2 +- .../tabs/ExplorerTabContextMenu.tsx | 65 ++++++++++++++++ .../explorer/components/tabs/ExplorerTabs.tsx | 29 ++++++- .../explorer/components/tabs/TableTabs.tsx} | 76 +++++++++++-------- .../explorer/hooks/useExplorerActions.ts | 2 - .../modules/explorer/hooks/useExplorerTabs.ts | 24 +++++- .../modules/explorer/pages/explorer.page.tsx | 2 + .../src/shared/hooks/useContextMenu.ts | 22 ++++++ .../sidebar/components/ConnectionItem.tsx | 26 ++----- 9 files changed, 188 insertions(+), 60 deletions(-) create mode 100644 apps/desktop/renderer/src/modules/explorer/components/tabs/ExplorerTabContextMenu.tsx rename apps/desktop/renderer/src/{shared/components/table-tabs.tsx => modules/explorer/components/tabs/TableTabs.tsx} (62%) create mode 100644 apps/desktop/renderer/src/shared/hooks/useContextMenu.ts diff --git a/.github/scripts/telegram-notify.js b/.github/scripts/telegram-notify.js index 6b52de8..3734bbc 100644 --- a/.github/scripts/telegram-notify.js +++ b/.github/scripts/telegram-notify.js @@ -25,7 +25,7 @@ if (GITHUB_EVENT_PATH && fs.existsSync(GITHUB_EVENT_PATH)) { if (GITHUB_EVENT_NAME === 'push') { message += `\n*Push*\n\n` - message += `Branch: ${GITHUB_REF?.replace('refs/heads/', '')}\n` + message += `Branch: ${GITHUB_REF?.replace('refs/heads/', '')}\n\n` payload.commits?.slice(0, 3).forEach((c, i) => { message += `${i + 1}. ${c.message.split('\n')[0]}\n` diff --git a/apps/desktop/renderer/src/modules/explorer/components/tabs/ExplorerTabContextMenu.tsx b/apps/desktop/renderer/src/modules/explorer/components/tabs/ExplorerTabContextMenu.tsx new file mode 100644 index 0000000..d39940c --- /dev/null +++ b/apps/desktop/renderer/src/modules/explorer/components/tabs/ExplorerTabContextMenu.tsx @@ -0,0 +1,65 @@ +import type { ReactNode } from 'react' + +import { useContextMenu } from '@/shared/hooks/useContextMenu' +import { DropdownMenu, DropdownMenuContent, DropdownMenuItem } from '@/shared/ui/dropdown-menu' + +interface Props { + children: ReactNode + disabledCloseOthers: boolean + onClose: () => void + onCloseOthers: () => void + onCloseAll: () => void +} +export function ExplorerTabContextMenu({ + children, + disabledCloseOthers, + onClose, + onCloseOthers, + onCloseAll +}: Props) { + const { open, position, onContextMenu, close } = useContextMenu() + + return ( + <> +
{children}
+ + {open && ( + !val && close()}> + + { + onClose() + close() + }} + > + Close + + { + onCloseOthers() + close() + }} + > + Close Others + + { + onCloseAll() + close() + }} + > + Close All + + + + )} + + ) +} diff --git a/apps/desktop/renderer/src/modules/explorer/components/tabs/ExplorerTabs.tsx b/apps/desktop/renderer/src/modules/explorer/components/tabs/ExplorerTabs.tsx index cdb83dc..0a80da5 100644 --- a/apps/desktop/renderer/src/modules/explorer/components/tabs/ExplorerTabs.tsx +++ b/apps/desktop/renderer/src/modules/explorer/components/tabs/ExplorerTabs.tsx @@ -2,8 +2,9 @@ import type { ReactNode } from 'react' import type { Tab } from '../../types/explorer.types' +import { ExplorerTabContextMenu } from './ExplorerTabContextMenu' import { TabContent } from './TabContent' -import { TableTabs } from '@/shared/components/table-tabs' +import { TableTabs } from './TableTabs' import { cn } from '@/shared/lib/utils' interface Props { @@ -11,10 +12,19 @@ interface Props { activeTab: string onSelectTab: (id: string) => void onCloseTab: (id: string) => void + onCloseOthers: (id: string) => void + onCloseAll: () => void children?: ReactNode } -export function ExplorerTabs({ tabs, activeTab, onSelectTab, onCloseTab }: Props) { +export function ExplorerTabs({ + tabs, + activeTab, + onSelectTab, + onCloseTab, + onCloseOthers, + onCloseAll +}: Props) { return (
( + onCloseTab(tab.id)} + onCloseOthers={() => { + onSelectTab(tab.id) + onCloseOthers(tab.id) + }} + onCloseAll={() => { + onCloseAll() + }} + > +
{tabNode}
+
+ )} > {tabs.map(tab => (
void onCloseTab: (id: string) => void - children: React.ReactNode + renderTab?: (tab: Tab, defaultTab: ReactNode) => ReactNode + children: ReactNode } -export function TableTabs({ tabs, activeTab, onSelectTab, onCloseTab, children }: TableTabsProps) { +export function TableTabs({ + tabs, + activeTab, + onSelectTab, + onCloseTab, + renderTab, + children +}: TableTabsProps) { const tabsRef = useRef(null) const [showScrollButtons, setShowScrollButtons] = useState(false) @@ -61,38 +68,42 @@ export function TableTabs({ tabs, activeTab, onSelectTab, onCloseTab, children } )}
- {tabs.map(tab => ( -