diff --git a/apps/frontend/src/renderer/components/ProjectTabBar.tsx b/apps/frontend/src/renderer/components/ProjectTabBar.tsx
index 1f476ce2..5c12e47b 100644
--- a/apps/frontend/src/renderer/components/ProjectTabBar.tsx
+++ b/apps/frontend/src/renderer/components/ProjectTabBar.tsx
@@ -30,7 +30,7 @@ export function ProjectTabBar({
onSettingsClick
}: ProjectTabBarProps) {
const { t } = useTranslation('common');
- const { isProjectPoppedOut, setWindowLoading, addPoppedOutProject } = useWindowStore();
+ const { isProjectPoppedOut, setWindowLoading, addPoppedOutProject, isWindowLoading } = useWindowStore();
// Handler for popping out a project into a new window
const handlePopOutProject = async (projectId: string) => {
@@ -148,6 +148,7 @@ export function ProjectTabBar({
onSettingsClick={isActiveTab ? onSettingsClick : undefined}
onPopOutClick={isActiveTab ? () => handlePopOutProject(project.id) : undefined}
isPoppedOut={isProjectPoppedOut(project.id)}
+ isLoading={isWindowLoading(project.id)}
/>
);
})}
diff --git a/apps/frontend/src/renderer/components/Sidebar.tsx b/apps/frontend/src/renderer/components/Sidebar.tsx
index 505843ae..21fd7a28 100644
--- a/apps/frontend/src/renderer/components/Sidebar.tsx
+++ b/apps/frontend/src/renderer/components/Sidebar.tsx
@@ -23,7 +23,8 @@ import {
Wrench,
PanelLeft,
PanelLeftClose,
- ExternalLink
+ ExternalLink,
+ Loader2
} from 'lucide-react';
import { Button } from './ui/button';
import { ScrollArea } from './ui/scroll-area';
@@ -113,7 +114,7 @@ export function Sidebar({
const projects = useProjectStore((state) => state.projects);
const selectedProjectId = useProjectStore((state) => state.selectedProjectId);
const settings = useSettingsStore((state) => state.settings);
- const { isViewPoppedOut, setWindowLoading, addPoppedOutView } = useWindowStore();
+ const { isViewPoppedOut, setWindowLoading, addPoppedOutView, isWindowLoading, getViewKey } = useWindowStore();
const [showAddProjectModal, setShowAddProjectModal] = useState(false);
const [showInitDialog, setShowInitDialog] = useState(false);
@@ -338,6 +339,8 @@ export function Sidebar({
const isActive = activeView === item.id;
const Icon = item.icon;
const isPoppedOut = selectedProjectId ? isViewPoppedOut(selectedProjectId, item.id) : false;
+ const viewKey = selectedProjectId ? getViewKey(selectedProjectId, item.id) : '';
+ const isLoading = viewKey ? isWindowLoading(viewKey) : false;
const button = (
{
e.stopPropagation();
- if (!isPoppedOut) {
+ if (!isPoppedOut && !isLoading) {
handlePopOutView(item.id, e);
}
}}
- disabled={isPoppedOut}
+ disabled={isPoppedOut || isLoading}
aria-label={isPoppedOut ? t('navigation:viewPoppedOut') : t('navigation:popOutView')}
className={cn(
'h-5 w-5 p-0 rounded flex items-center justify-center',
'text-muted-foreground hover:text-foreground',
'hover:bg-muted/50 transition-colors',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1',
- isPoppedOut ? 'opacity-100 text-primary' : 'opacity-0 group-hover:opacity-100',
- isPoppedOut && 'cursor-not-allowed'
+ isPoppedOut || isLoading ? 'opacity-100' : 'opacity-0 group-hover:opacity-100',
+ isPoppedOut && 'text-primary',
+ (isPoppedOut || isLoading) && 'cursor-not-allowed'
)}
>
-
+ {isLoading ? (
+
+ ) : (
+
+ )}
- {isPoppedOut ? t('navigation:tooltips.viewPoppedOut') : t('navigation:tooltips.popOutView')}
+ {isLoading ? t('navigation:tooltips.popOutLoading') : isPoppedOut ? t('navigation:tooltips.viewPoppedOut') : t('navigation:tooltips.popOutView')}
)}
diff --git a/apps/frontend/src/renderer/components/SortableProjectTab.tsx b/apps/frontend/src/renderer/components/SortableProjectTab.tsx
index 4111003d..ba4e0b15 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, ExternalLink } from 'lucide-react';
+import { Settings2, ExternalLink, Loader2 } from 'lucide-react';
import { cn } from '../lib/utils';
import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip';
import type { Project } from '../../shared/types';
@@ -17,6 +17,7 @@ interface SortableProjectTabProps {
onSettingsClick?: () => void;
onPopOutClick?: () => void;
isPoppedOut?: boolean;
+ isLoading?: boolean;
}
// Detect if running on macOS for keyboard shortcut display
@@ -32,7 +33,8 @@ export function SortableProjectTab({
onClose,
onSettingsClick,
onPopOutClick,
- isPoppedOut = false
+ isPoppedOut = false,
+ isLoading = false
}: SortableProjectTabProps) {
const { t } = useTranslation('common');
// Build tooltip with keyboard shortcut hint (only for tabs 1-9)
@@ -138,22 +140,26 @@ export function SortableProjectTab({
'text-muted-foreground hover:text-foreground',
'hover:bg-muted/50 transition-colors',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1',
- isPoppedOut && 'opacity-50 cursor-not-allowed'
+ (isPoppedOut || isLoading) && 'opacity-50 cursor-not-allowed'
)}
onClick={(e) => {
e.stopPropagation();
- if (!isPoppedOut) {
+ if (!isPoppedOut && !isLoading) {
onPopOutClick();
}
}}
- disabled={isPoppedOut}
+ disabled={isPoppedOut || isLoading}
aria-label={t('projectTab.popOutAriaLabel')}
>
-
+ {isLoading ? (
+
+ ) : (
+
+ )}
- {t('projectTab.popOut')}
+ {isLoading ? t('projectTab.popOutLoading') : t('projectTab.popOut')}
)}
diff --git a/apps/frontend/src/shared/i18n/locales/en/common.json b/apps/frontend/src/shared/i18n/locales/en/common.json
index 48aeef89..67da5dd5 100644
--- a/apps/frontend/src/shared/i18n/locales/en/common.json
+++ b/apps/frontend/src/shared/i18n/locales/en/common.json
@@ -10,6 +10,7 @@
"addProjectAriaLabel": "Add project",
"popOut": "Pop out project",
"popOutAriaLabel": "Pop out project into separate window",
+ "popOutLoading": "Creating window...",
"poppedOutBadge": "Popped Out"
},
"accessibility": {
diff --git a/apps/frontend/src/shared/i18n/locales/en/navigation.json b/apps/frontend/src/shared/i18n/locales/en/navigation.json
index 055b4fdd..12c4037d 100644
--- a/apps/frontend/src/shared/i18n/locales/en/navigation.json
+++ b/apps/frontend/src/shared/i18n/locales/en/navigation.json
@@ -32,7 +32,8 @@
"settings": "Application Settings",
"help": "Help & Feedback",
"popOutView": "Open this view in a separate window",
- "viewPoppedOut": "This view is opened in a separate window"
+ "viewPoppedOut": "This view is opened in a separate window",
+ "popOutLoading": "Creating window..."
},
"messages": {
"initializeToCreateTasks": "Initialize Auto Claude to create tasks"
diff --git a/apps/frontend/src/shared/i18n/locales/fr/common.json b/apps/frontend/src/shared/i18n/locales/fr/common.json
index ec5b8a34..71d9ac37 100644
--- a/apps/frontend/src/shared/i18n/locales/fr/common.json
+++ b/apps/frontend/src/shared/i18n/locales/fr/common.json
@@ -10,6 +10,7 @@
"addProjectAriaLabel": "Ajouter un projet",
"popOut": "Ouvrir dans une fenêtre séparée",
"popOutAriaLabel": "Ouvrir le projet dans une fenêtre séparée",
+ "popOutLoading": "Création de la fenêtre...",
"poppedOutBadge": "Détaché"
},
"accessibility": {
diff --git a/apps/frontend/src/shared/i18n/locales/fr/navigation.json b/apps/frontend/src/shared/i18n/locales/fr/navigation.json
index b1e08b4e..afc54c84 100644
--- a/apps/frontend/src/shared/i18n/locales/fr/navigation.json
+++ b/apps/frontend/src/shared/i18n/locales/fr/navigation.json
@@ -32,7 +32,8 @@
"settings": "Paramètres de l'application",
"help": "Aide & Feedback",
"popOutView": "Ouvrir cette vue dans une fenêtre séparée",
- "viewPoppedOut": "Cette vue est ouverte dans une fenêtre séparée"
+ "viewPoppedOut": "Cette vue est ouverte dans une fenêtre séparée",
+ "popOutLoading": "Création de la fenêtre..."
},
"messages": {
"initializeToCreateTasks": "Initialisez Auto Claude pour créer des tâches"