+
{/* Menu Overlay */}
{menuOpen && (
diff --git a/src/renderer/components/FeedbackChatView.tsx b/src/renderer/components/FeedbackChatView.tsx
index 1d822b28ca..0e1933992d 100644
--- a/src/renderer/components/FeedbackChatView.tsx
+++ b/src/renderer/components/FeedbackChatView.tsx
@@ -16,7 +16,6 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
ImagePlus,
- Loader2,
MessageSquareHeart,
Send,
X,
@@ -28,6 +27,7 @@ import {
Check,
Copy,
} from 'lucide-react';
+import { Spinner } from './ui/Spinner';
import { safeClipboardWrite } from '../utils/clipboard';
import { MarkdownRenderer } from './MarkdownRenderer';
import { generateTerminalProseStyles } from '../utils/markdownConfig';
@@ -517,7 +517,7 @@ export function FeedbackChatView({ theme, onCancel, onWidthChange }: FeedbackCha
if (ghAuth.checking) {
return (
-
+
Checking GitHub CLI...
@@ -674,7 +674,7 @@ export function FeedbackChatView({ theme, onCancel, onWidthChange }: FeedbackCha
{searchingIssues ? (
-
+
Searching for similar existing issues...
@@ -750,7 +750,7 @@ export function FeedbackChatView({ theme, onCancel, onWidthChange }: FeedbackCha
title="Subscribe and add your feedback as a comment"
>
{subscribingTo === issue.number ? (
-
+
) : (
)}
@@ -825,7 +825,7 @@ export function FeedbackChatView({ theme, onCancel, onWidthChange }: FeedbackCha
className="flex items-center gap-1 text-[10px]"
style={{ color: theme.colors.textDim }}
>
-
+
Checking for similar issues...
)}
@@ -843,11 +843,7 @@ export function FeedbackChatView({ theme, onCancel, onWidthChange }: FeedbackCha
className="flex items-center gap-1.5 px-3 py-1 rounded text-xs font-bold transition-colors hover:opacity-90 disabled:opacity-40 shrink-0"
style={{ backgroundColor: theme.colors.success, color: '#000' }}
>
- {step === 'submitting' ? (
-
- ) : (
-
- )}
+ {step === 'submitting' ?
:
}
Submit Feedback
)}
@@ -902,7 +898,7 @@ export function FeedbackChatView({ theme, onCancel, onWidthChange }: FeedbackCha
border: `1px solid ${theme.colors.border}`,
}}
>
-
+
)}
@@ -966,7 +962,7 @@ export function FeedbackChatView({ theme, onCancel, onWidthChange }: FeedbackCha
title="Subscribe and add your feedback as a comment"
>
{subscribingTo === issue.number ? (
-
+
) : (
)}
@@ -1125,11 +1121,7 @@ export function FeedbackChatView({ theme, onCancel, onWidthChange }: FeedbackCha
style={{ backgroundColor: theme.colors.accent, color: theme.colors.accentForeground }}
title="Send message"
>
- {isLoading ? (
-
- ) : (
-
- )}
+ {isLoading ?
:
}
{/* Submit button — appears when ready */}
{isReady && (
@@ -1141,11 +1133,7 @@ export function FeedbackChatView({ theme, onCancel, onWidthChange }: FeedbackCha
style={{ backgroundColor: theme.colors.success, color: '#000' }}
title="Submit feedback as GitHub issue"
>
- {step === 'submitting' ? (
-
- ) : (
-
- )}
+ {step === 'submitting' ?
:
}
Submit
)}
diff --git a/src/renderer/components/FileExplorerPanel.tsx b/src/renderer/components/FileExplorerPanel.tsx
index f90404f4fc..8668747587 100644
--- a/src/renderer/components/FileExplorerPanel.tsx
+++ b/src/renderer/components/FileExplorerPanel.tsx
@@ -21,9 +21,9 @@ import {
Edit2,
Trash2,
AlertTriangle,
- Loader2,
Search,
} from 'lucide-react';
+import { Spinner } from './ui/Spinner';
import type { Session, Theme, FocusArea } from '../types';
import type { FileNode } from '../types/fileTree';
import type { FileTreeChanges } from '../utils/fileExplorer';
@@ -114,7 +114,7 @@ function FileTreeLoadingProgress({
return (
{/* Animated spinner */}
-
+
{/* Status text */}
diff --git a/src/renderer/components/FilePreview/FilePreview.tsx b/src/renderer/components/FilePreview/FilePreview.tsx
index 79759e8737..95e53f3edf 100644
--- a/src/renderer/components/FilePreview/FilePreview.tsx
+++ b/src/renderer/components/FilePreview/FilePreview.tsx
@@ -21,6 +21,7 @@ import {
X,
Filter,
} from 'lucide-react';
+import { GhostIconButton } from '../ui/GhostIconButton';
import { captureException } from '../../utils/sentry';
import { safeClipboardWrite, safeClipboardWriteBlob } from '../../utils/clipboard';
import { useLayerStack } from '../../contexts/LayerStackContext';
@@ -998,13 +999,9 @@ export const FilePreview = React.memo(
>
Reload
-
+
)}
diff --git a/src/renderer/components/FilePreview/FilePreviewHeader.tsx b/src/renderer/components/FilePreview/FilePreviewHeader.tsx
index 16240f15dd..6a61d63efe 100644
--- a/src/renderer/components/FilePreview/FilePreviewHeader.tsx
+++ b/src/renderer/components/FilePreview/FilePreviewHeader.tsx
@@ -6,7 +6,6 @@ import {
ChevronRight,
Clipboard,
Copy,
- Loader2,
Globe,
Save,
Edit,
@@ -14,6 +13,7 @@ import {
GitGraph,
ExternalLink,
} from 'lucide-react';
+import { Spinner } from '../ui/Spinner';
import { captureException } from '../../utils/sentry';
import { formatShortcutKeys } from '../../utils/shortcutFormatter';
import { formatFileSize, formatDateTime } from './filePreviewUtils';
@@ -145,11 +145,7 @@ export const FilePreviewHeader = React.memo(function FilePreviewHeader({
: 'No changes to save'
}
>
- {isSaving ? (
-
- ) : (
-
- )}
+ {isSaving ?
:
}
{isSaving ? 'Saving...' : 'Save'}
)}
diff --git a/src/renderer/components/FilePreview/ImageViewer.tsx b/src/renderer/components/FilePreview/ImageViewer.tsx
index d3b5976299..17efebbdba 100644
--- a/src/renderer/components/FilePreview/ImageViewer.tsx
+++ b/src/renderer/components/FilePreview/ImageViewer.tsx
@@ -1,6 +1,7 @@
import React, { useState, useRef, useCallback, useEffect, memo } from 'react';
import { ZoomIn, ZoomOut, Maximize2 } from 'lucide-react';
+import { GhostIconButton } from '../ui/GhostIconButton';
interface ImageViewerProps {
src: string;
alt: string;
@@ -118,36 +119,21 @@ export const ImageViewer = memo(function ImageViewer({ src, alt, theme }: ImageV
className="flex items-center justify-center gap-2 py-1.5 shrink-0 border-b"
style={{ borderColor: theme.colors.border }}
>
-
+
{zoomPercent}%
-
-
+
{naturalSize && (
{naturalSize.w} × {naturalSize.h}
diff --git a/src/renderer/components/FilePreview/MarkdownImage.tsx b/src/renderer/components/FilePreview/MarkdownImage.tsx
index ad7a5d4d2f..b3299117ca 100644
--- a/src/renderer/components/FilePreview/MarkdownImage.tsx
+++ b/src/renderer/components/FilePreview/MarkdownImage.tsx
@@ -1,5 +1,6 @@
import React, { useState, useMemo, useEffect, useCallback } from 'react';
-import { Loader2, Image } from 'lucide-react';
+import { Image } from 'lucide-react';
+import { Spinner } from '../ui/Spinner';
import { imageCache, resolveImagePath } from './filePreviewUtils';
/**
@@ -138,7 +139,7 @@ export const MarkdownImage = React.memo(function MarkdownImage({
minWidth: '200px',
}}
>
-
+
Loading image...
diff --git a/src/renderer/components/GistPublishModal.tsx b/src/renderer/components/GistPublishModal.tsx
index 685c92c239..61e2e5db2c 100644
--- a/src/renderer/components/GistPublishModal.tsx
+++ b/src/renderer/components/GistPublishModal.tsx
@@ -1,5 +1,6 @@
import { useRef, useState, useCallback } from 'react';
import { Share2, Copy, Check, ExternalLink } from 'lucide-react';
+import { GhostIconButton } from './ui/GhostIconButton';
import type { Theme } from '../types';
import { MODAL_PRIORITIES } from '../constants/modalPriorities';
import { Modal } from './ui/Modal';
@@ -180,24 +181,22 @@ export function GistPublishModal({
style={{ color: theme.colors.textMain }}
onClick={(e) => (e.target as HTMLInputElement).select()}
/>
-
-
+
diff --git a/src/renderer/components/GroupChatModal.tsx b/src/renderer/components/GroupChatModal.tsx
index 04c8888d7a..e44c1d0d12 100644
--- a/src/renderer/components/GroupChatModal.tsx
+++ b/src/renderer/components/GroupChatModal.tsx
@@ -13,6 +13,7 @@
import { useState, useEffect, useRef, useCallback } from 'react';
import { X, Settings, ChevronDown, Check } from 'lucide-react';
+import { GhostIconButton } from './ui/GhostIconButton';
import { isBetaAgent } from '../../shared/agentMetadata';
import type { Theme, AgentConfig, ModeratorConfig, GroupChat } from '../types';
import { MODAL_PRIORITIES } from '../constants/modalPriorities';
@@ -242,15 +243,9 @@ export function GroupChatModal(props: GroupChatModalProps): JSX.Element | null {
Beta