diff --git a/apps/frontend/src/renderer/components/ProjectTabBar.tsx b/apps/frontend/src/renderer/components/ProjectTabBar.tsx index d76b34f4..9d89c07c 100644 --- a/apps/frontend/src/renderer/components/ProjectTabBar.tsx +++ b/apps/frontend/src/renderer/components/ProjectTabBar.tsx @@ -6,6 +6,7 @@ import { Button } from './ui/button'; import { SortableProjectTab } from './SortableProjectTab'; import { UsageIndicator } from './UsageIndicator'; import { AuthStatusIndicator } from './AuthStatusIndicator'; +import { useWindowStore } from '../stores/window-store'; import type { Project } from '../../shared/types'; interface ProjectTabBarProps { @@ -29,6 +30,22 @@ export function ProjectTabBar({ onSettingsClick }: ProjectTabBarProps) { const { t } = useTranslation('common'); + const { isProjectPoppedOut, setWindowLoading, addPoppedOutProject } = useWindowStore(); + + // Handler for popping out a project into a new window + const handlePopOutProject = async (projectId: string) => { + try { + setWindowLoading(projectId, true); + const { windowId } = await window.electronAPI.window.popOutProject(projectId); + addPoppedOutProject(projectId); + console.log(`Project ${projectId} popped out to window ${windowId}`); + } catch (error) { + console.error('Failed to pop out project:', error); + // TODO: Show error notification to user + } finally { + setWindowLoading(projectId, false); + } + }; // Keyboard shortcuts for tab navigation useEffect(() => { @@ -107,6 +124,8 @@ export function ProjectTabBar({ }} // Pass control props only for active tab onSettingsClick={isActiveTab ? onSettingsClick : undefined} + onPopOutClick={isActiveTab ? () => handlePopOutProject(project.id) : undefined} + isPoppedOut={isProjectPoppedOut(project.id)} /> ); })} diff --git a/apps/frontend/src/renderer/components/SortableProjectTab.tsx b/apps/frontend/src/renderer/components/SortableProjectTab.tsx index d57cf129..9ffcc4a3 100644 --- a/apps/frontend/src/renderer/components/SortableProjectTab.tsx +++ b/apps/frontend/src/renderer/components/SortableProjectTab.tsx @@ -1,7 +1,7 @@ import { useSortable } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import { useTranslation } from 'react-i18next'; -import { Settings2 } from 'lucide-react'; +import { Settings2, ExternalLink } from 'lucide-react'; import { cn } from '../lib/utils'; import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip'; import type { Project } from '../../shared/types'; @@ -15,6 +15,8 @@ interface SortableProjectTabProps { onClose: (e: React.MouseEvent) => void; // Optional control props for active tab onSettingsClick?: () => void; + onPopOutClick?: () => void; + isPoppedOut?: boolean; } // Detect if running on macOS for keyboard shortcut display @@ -28,7 +30,9 @@ export function SortableProjectTab({ tabIndex, onSelect, onClose, - onSettingsClick + onSettingsClick, + onPopOutClick, + isPoppedOut = false }: SortableProjectTabProps) { const { t } = useTranslation('common'); // Build tooltip with keyboard shortcut hint (only for tabs 1-9) @@ -112,9 +116,40 @@ export function SortableProjectTab({ - {/* Active tab controls - settings and archive, always accessible */} + {/* Active tab controls - settings, pop-out, always accessible */} {isActive && (
+ {/* Pop-out icon - responsive sizing */} + {onPopOutClick && ( + + + + + + {t('projectTab.popOut')} + + + )} {/* Settings icon - responsive sizing */} {onSettingsClick && ( diff --git a/apps/frontend/src/shared/i18n/locales/en/common.json b/apps/frontend/src/shared/i18n/locales/en/common.json index 8078a129..84763e96 100644 --- a/apps/frontend/src/shared/i18n/locales/en/common.json +++ b/apps/frontend/src/shared/i18n/locales/en/common.json @@ -7,7 +7,9 @@ "hideArchivedTasks": "Hide archived tasks", "closeTab": "Close tab", "closeTabAriaLabel": "Close tab (removes project from app)", - "addProjectAriaLabel": "Add project" + "addProjectAriaLabel": "Add project", + "popOut": "Pop out project", + "popOutAriaLabel": "Pop out project into separate window" }, "accessibility": { "deleteFeatureAriaLabel": "Delete feature", diff --git a/apps/frontend/src/shared/i18n/locales/fr/common.json b/apps/frontend/src/shared/i18n/locales/fr/common.json index d2c452b7..94671a4f 100644 --- a/apps/frontend/src/shared/i18n/locales/fr/common.json +++ b/apps/frontend/src/shared/i18n/locales/fr/common.json @@ -7,7 +7,9 @@ "hideArchivedTasks": "Masquer les tâches archivées", "closeTab": "Fermer l'onglet", "closeTabAriaLabel": "Fermer l'onglet (retire le projet de l'application)", - "addProjectAriaLabel": "Ajouter un projet" + "addProjectAriaLabel": "Ajouter un projet", + "popOut": "Ouvrir dans une fenêtre séparée", + "popOutAriaLabel": "Ouvrir le projet dans une fenêtre séparée" }, "accessibility": { "deleteFeatureAriaLabel": "Supprimer la fonctionnalité",