mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 08:33:36 +00:00
refactor: replace Loader2 with Spinner component across the application
This update standardizes the loading indicators by replacing all instances of Loader2 with the new Spinner component. The Spinner component provides a consistent look and feel for loading states throughout the UI, enhancing the user experience. Changes include: - Updated loading indicators in various components such as popovers, modals, and views. - Ensured that the Spinner component is used with appropriate sizes for different contexts. No functional changes were made; this is purely a visual and structural improvement.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useRef, useEffect } from 'react';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Search, X, Loader2 } from 'lucide-react';
|
||||
import { Search, X } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
|
||||
interface BoardSearchBarProps {
|
||||
searchQuery: string;
|
||||
@@ -75,7 +76,7 @@ export function BoardSearchBar({
|
||||
title="Creating App Specification"
|
||||
data-testid="spec-creation-badge"
|
||||
>
|
||||
<Loader2 className="w-3 h-3 animate-spin text-brand-500 shrink-0" />
|
||||
<Spinner size="xs" className="shrink-0" />
|
||||
<span className="text-xs font-medium text-brand-500 whitespace-nowrap">
|
||||
Creating spec
|
||||
</span>
|
||||
|
||||
@@ -11,16 +11,8 @@ import {
|
||||
} from '@/lib/agent-context-parser';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { AutoModeEvent } from '@/types/electron';
|
||||
import {
|
||||
Brain,
|
||||
ListTodo,
|
||||
Sparkles,
|
||||
Expand,
|
||||
CheckCircle2,
|
||||
Circle,
|
||||
Loader2,
|
||||
Wrench,
|
||||
} from 'lucide-react';
|
||||
import { Brain, ListTodo, Sparkles, Expand, CheckCircle2, Circle, Wrench } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { SummaryDialog } from './summary-dialog';
|
||||
import { getProviderIconForModel } from '@/components/ui/provider-icon';
|
||||
@@ -338,7 +330,7 @@ export function AgentInfoPanel({
|
||||
{todo.status === 'completed' ? (
|
||||
<CheckCircle2 className="w-2.5 h-2.5 text-[var(--status-success)] shrink-0" />
|
||||
) : todo.status === 'in_progress' ? (
|
||||
<Loader2 className="w-2.5 h-2.5 text-[var(--status-warning)] animate-spin shrink-0" />
|
||||
<Spinner size="xs" className="w-2.5 h-2.5 shrink-0" />
|
||||
) : (
|
||||
<Circle className="w-2.5 h-2.5 text-muted-foreground/50 shrink-0" />
|
||||
)}
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
import {
|
||||
GripVertical,
|
||||
Edit,
|
||||
Loader2,
|
||||
Trash2,
|
||||
FileText,
|
||||
MoreVertical,
|
||||
@@ -21,6 +20,7 @@ import {
|
||||
ChevronUp,
|
||||
GitFork,
|
||||
} from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { CountUpTimer } from '@/components/ui/count-up-timer';
|
||||
import { formatModelName, DEFAULT_MODEL } from '@/lib/agent-context-parser';
|
||||
import { DeleteConfirmDialog } from '@/components/ui/delete-confirm-dialog';
|
||||
@@ -65,7 +65,7 @@ export function CardHeaderSection({
|
||||
{isCurrentAutoTask && !isSelectionMode && (
|
||||
<div className="absolute top-2 right-2 flex items-center gap-1">
|
||||
<div className="flex items-center justify-center gap-2 bg-[var(--status-in-progress)]/15 border border-[var(--status-in-progress)]/50 rounded-md px-2 py-0.5">
|
||||
<Loader2 className="w-3.5 h-3.5 text-[var(--status-in-progress)] animate-spin" />
|
||||
<Spinner size="xs" />
|
||||
{feature.startedAt && (
|
||||
<CountUpTimer
|
||||
startedAt={feature.startedAt}
|
||||
@@ -324,7 +324,7 @@ export function CardHeaderSection({
|
||||
<div className="flex-1 min-w-0 overflow-hidden">
|
||||
{feature.titleGenerating ? (
|
||||
<div className="flex items-center gap-1.5 mb-1">
|
||||
<Loader2 className="w-3 h-3 animate-spin text-muted-foreground" />
|
||||
<Spinner size="xs" />
|
||||
<span className="text-xs text-muted-foreground italic">Generating title...</span>
|
||||
</div>
|
||||
) : feature.title ? (
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { Loader2, List, FileText, GitBranch, ClipboardList } from 'lucide-react';
|
||||
import { List, FileText, GitBranch, ClipboardList } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { LogViewer } from '@/components/ui/log-viewer';
|
||||
import { GitDiffPanel } from '@/components/ui/git-diff-panel';
|
||||
@@ -353,7 +354,7 @@ export function AgentOutputModal({
|
||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 pr-8">
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
{featureStatus !== 'verified' && featureStatus !== 'waiting_approval' && (
|
||||
<Loader2 className="w-5 h-5 text-primary animate-spin" />
|
||||
<Spinner size="md" />
|
||||
)}
|
||||
Agent Output
|
||||
</DialogTitle>
|
||||
@@ -439,7 +440,7 @@ export function AgentOutputModal({
|
||||
/>
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-full text-muted-foreground">
|
||||
<Loader2 className="w-6 h-6 animate-spin mr-2" />
|
||||
<Spinner size="lg" className="mr-2" />
|
||||
Loading...
|
||||
</div>
|
||||
)}
|
||||
@@ -457,7 +458,7 @@ export function AgentOutputModal({
|
||||
>
|
||||
{isLoading && !output ? (
|
||||
<div className="flex items-center justify-center h-full text-muted-foreground">
|
||||
<Loader2 className="w-6 h-6 animate-spin mr-2" />
|
||||
<Spinner size="lg" className="mr-2" />
|
||||
Loading output...
|
||||
</div>
|
||||
) : !output ? (
|
||||
|
||||
@@ -11,16 +11,8 @@ import {
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import {
|
||||
Loader2,
|
||||
Wand2,
|
||||
Check,
|
||||
Plus,
|
||||
Pencil,
|
||||
Trash2,
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
} from 'lucide-react';
|
||||
import { Wand2, Check, Plus, Pencil, Trash2, ChevronDown, ChevronRight } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { toast } from 'sonner';
|
||||
import { cn } from '@/lib/utils';
|
||||
@@ -287,8 +279,7 @@ export function BacklogPlanDialog({
|
||||
</div>
|
||||
{isGeneratingPlan && (
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground bg-muted/50 rounded-lg p-3">
|
||||
<Loader2 className="w-4 h-4 animate-spin" />A plan is currently being generated in
|
||||
the background...
|
||||
<Spinner size="sm" />A plan is currently being generated in the background...
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -405,7 +396,7 @@ export function BacklogPlanDialog({
|
||||
case 'applying':
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center py-12">
|
||||
<Loader2 className="w-8 h-8 animate-spin text-primary mb-4" />
|
||||
<Spinner size="xl" className="mb-4" />
|
||||
<p className="text-muted-foreground">Applying changes...</p>
|
||||
</div>
|
||||
);
|
||||
@@ -452,7 +443,7 @@ export function BacklogPlanDialog({
|
||||
<Button onClick={handleGenerate} disabled={!prompt.trim() || isGeneratingPlan}>
|
||||
{isGeneratingPlan ? (
|
||||
<>
|
||||
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
||||
<Spinner size="sm" className="mr-2" />
|
||||
Generating...
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -10,7 +10,8 @@ import {
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { GitCommit, Loader2, Sparkles } from 'lucide-react';
|
||||
import { GitCommit, Sparkles } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { toast } from 'sonner';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
@@ -209,7 +210,7 @@ export function CommitWorktreeDialog({
|
||||
<Button onClick={handleCommit} disabled={isLoading || isGenerating || !message.trim()}>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
||||
<Spinner size="sm" className="mr-2" />
|
||||
Committing...
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -13,7 +13,8 @@ import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { toast } from 'sonner';
|
||||
import { GitBranchPlus, Loader2 } from 'lucide-react';
|
||||
import { GitBranchPlus } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
|
||||
interface WorktreeInfo {
|
||||
path: string;
|
||||
@@ -133,7 +134,7 @@ export function CreateBranchDialog({
|
||||
<Button onClick={handleCreate} disabled={!branchName.trim() || isCreating}>
|
||||
{isCreating ? (
|
||||
<>
|
||||
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
||||
<Spinner size="sm" className="mr-2" />
|
||||
Creating...
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -13,7 +13,8 @@ import { Textarea } from '@/components/ui/textarea';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { BranchAutocomplete } from '@/components/ui/branch-autocomplete';
|
||||
import { GitPullRequest, Loader2, ExternalLink } from 'lucide-react';
|
||||
import { GitPullRequest, ExternalLink } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
@@ -405,7 +406,7 @@ export function CreatePRDialog({
|
||||
<Button onClick={handleCreate} disabled={isLoading}>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
||||
<Spinner size="sm" className="mr-2" />
|
||||
Creating...
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -10,7 +10,8 @@ import {
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { GitBranch, Loader2, AlertCircle } from 'lucide-react';
|
||||
import { GitBranch, AlertCircle } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
@@ -216,7 +217,7 @@ export function CreateWorktreeDialog({
|
||||
<Button onClick={handleCreate} disabled={isLoading || !branchName.trim()}>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
||||
<Spinner size="sm" className="mr-2" />
|
||||
Creating...
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -10,7 +10,8 @@ import {
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Loader2, Trash2, AlertTriangle, FileWarning } from 'lucide-react';
|
||||
import { Trash2, AlertTriangle, FileWarning } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
@@ -147,7 +148,7 @@ export function DeleteWorktreeDialog({
|
||||
<Button variant="destructive" onClick={handleDelete} disabled={isLoading}>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
||||
<Spinner size="sm" className="mr-2" />
|
||||
Deleting...
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -10,7 +10,8 @@ import {
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Loader2, GitMerge, AlertTriangle, CheckCircle2 } from 'lucide-react';
|
||||
import { GitMerge, AlertTriangle, CheckCircle2 } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
@@ -217,7 +218,7 @@ export function MergeWorktreeDialog({
|
||||
>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
||||
<Spinner size="sm" className="mr-2" />
|
||||
Merging...
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -14,7 +14,8 @@ import { Textarea } from '@/components/ui/textarea';
|
||||
import { Markdown } from '@/components/ui/markdown';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Feature } from '@/store/app-store';
|
||||
import { Check, RefreshCw, Edit2, Eye, Loader2 } from 'lucide-react';
|
||||
import { Check, RefreshCw, Edit2, Eye } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
|
||||
interface PlanApprovalDialogProps {
|
||||
open: boolean;
|
||||
@@ -171,7 +172,7 @@ export function PlanApprovalDialog({
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={handleReject} disabled={isLoading}>
|
||||
{isLoading ? (
|
||||
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
||||
<Spinner size="sm" className="mr-2" />
|
||||
) : (
|
||||
<RefreshCw className="w-4 h-4 mr-2" />
|
||||
)}
|
||||
@@ -190,7 +191,7 @@ export function PlanApprovalDialog({
|
||||
className="bg-green-600 hover:bg-green-700 text-white"
|
||||
>
|
||||
{isLoading ? (
|
||||
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
||||
<Spinner size="sm" className="mr-2" />
|
||||
) : (
|
||||
<Check className="w-4 h-4 mr-2" />
|
||||
)}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState, useRef, useEffect, useCallback } from 'react';
|
||||
import { Terminal, Check, X, Loader2, ChevronDown, ChevronUp } from 'lucide-react';
|
||||
import { Terminal, Check, X, ChevronDown, ChevronUp } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useAppStore, type InitScriptState } from '@/store/app-store';
|
||||
import { AnsiOutput } from '@/components/ui/ansi-output';
|
||||
@@ -65,7 +66,7 @@ function SingleIndicator({
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between p-3 border-b border-border/50">
|
||||
<div className="flex items-center gap-2">
|
||||
{status === 'running' && <Loader2 className="w-4 h-4 animate-spin text-blue-500" />}
|
||||
{status === 'running' && <Spinner size="sm" />}
|
||||
{status === 'success' && <Check className="w-4 h-4 text-green-500" />}
|
||||
{status === 'failed' && <X className="w-4 h-4 text-red-500" />}
|
||||
<span className="font-medium text-sm">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useCallback, useState, type ComponentType, type ReactNode } from 'react';
|
||||
import { RefreshCw } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import { AnthropicIcon, OpenAIIcon } from '@/components/ui/provider-icon';
|
||||
@@ -90,9 +91,11 @@ function UsageItem({
|
||||
className="p-1 rounded hover:bg-accent/50 transition-colors"
|
||||
title="Refresh usage"
|
||||
>
|
||||
<RefreshCw
|
||||
className={cn('w-3.5 h-3.5 text-muted-foreground', isLoading && 'animate-spin')}
|
||||
/>
|
||||
{isLoading ? (
|
||||
<Spinner size="xs" />
|
||||
) : (
|
||||
<RefreshCw className="w-3.5 h-3.5 text-muted-foreground" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<div className="pl-6 space-y-2">{children}</div>
|
||||
|
||||
@@ -11,7 +11,7 @@ import { getModelProvider, PROVIDER_PREFIXES, stripProviderPrefix } from '@autom
|
||||
import type { ModelProvider } from '@automaker/types';
|
||||
import { CLAUDE_MODELS, CURSOR_MODELS, ModelOption } from './model-constants';
|
||||
import { useEffect } from 'react';
|
||||
import { RefreshCw } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
|
||||
interface ModelSelectorProps {
|
||||
selectedModel: string; // Can be ModelAlias or "cursor-{id}"
|
||||
@@ -294,7 +294,7 @@ export function ModelSelector({
|
||||
{/* Loading state */}
|
||||
{codexModelsLoading && dynamicCodexModels.length === 0 && (
|
||||
<div className="flex items-center justify-center gap-2 p-6 text-sm text-muted-foreground">
|
||||
<RefreshCw className="w-4 h-4 animate-spin" />
|
||||
<Spinner size="sm" />
|
||||
Loading models...
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -6,12 +6,12 @@ import {
|
||||
ClipboardList,
|
||||
FileText,
|
||||
ScrollText,
|
||||
Loader2,
|
||||
Check,
|
||||
Eye,
|
||||
RefreshCw,
|
||||
Sparkles,
|
||||
} from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
@@ -236,7 +236,7 @@ export function PlanningModeSelector({
|
||||
<div className="flex items-center gap-2">
|
||||
{isGenerating ? (
|
||||
<>
|
||||
<Loader2 className="h-4 w-4 animate-spin text-primary" />
|
||||
<Spinner size="sm" />
|
||||
<span className="text-sm text-muted-foreground">
|
||||
Generating {mode === 'full' ? 'comprehensive spec' : 'spec'}...
|
||||
</span>
|
||||
|
||||
@@ -8,7 +8,8 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuLabel,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { GitBranch, RefreshCw, GitBranchPlus, Check, Search } from 'lucide-react';
|
||||
import { GitBranch, GitBranchPlus, Check, Search } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { WorktreeInfo, BranchInfo } from '../types';
|
||||
|
||||
@@ -81,7 +82,7 @@ export function BranchSwitchDropdown({
|
||||
<div className="max-h-[250px] overflow-y-auto">
|
||||
{isLoadingBranches ? (
|
||||
<DropdownMenuItem disabled className="text-xs">
|
||||
<RefreshCw className="w-3.5 h-3.5 mr-2 animate-spin" />
|
||||
<Spinner size="xs" className="mr-2" />
|
||||
Loading branches...
|
||||
</DropdownMenuItem>
|
||||
) : filteredBranches.length === 0 ? (
|
||||
|
||||
@@ -2,7 +2,6 @@ import { useEffect, useRef, useCallback, useState } from 'react';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Loader2,
|
||||
Terminal,
|
||||
ArrowDown,
|
||||
ExternalLink,
|
||||
@@ -12,6 +11,7 @@ import {
|
||||
Clock,
|
||||
GitBranch,
|
||||
} from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { XtermLogViewer, type XtermLogViewerRef } from '@/components/ui/xterm-log-viewer';
|
||||
import { useDevServerLogs } from '../hooks/use-dev-server-logs';
|
||||
@@ -183,7 +183,7 @@ export function DevServerLogsPanel({
|
||||
onClick={() => fetchLogs()}
|
||||
title="Refresh logs"
|
||||
>
|
||||
<RefreshCw className={cn('w-3.5 h-3.5', isLoading && 'animate-spin')} />
|
||||
{isLoading ? <Spinner size="xs" /> : <RefreshCw className="w-3.5 h-3.5" />}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -234,7 +234,7 @@ export function DevServerLogsPanel({
|
||||
>
|
||||
{isLoading && !logs ? (
|
||||
<div className="flex items-center justify-center h-full min-h-[300px] text-muted-foreground">
|
||||
<Loader2 className="w-5 h-5 animate-spin mr-2" />
|
||||
<Spinner size="md" className="mr-2" />
|
||||
<span className="text-sm">Loading logs...</span>
|
||||
</div>
|
||||
) : !logs && !isRunning ? (
|
||||
@@ -245,7 +245,7 @@ export function DevServerLogsPanel({
|
||||
</div>
|
||||
) : !logs ? (
|
||||
<div className="flex flex-col items-center justify-center h-full min-h-[300px] text-muted-foreground p-8">
|
||||
<div className="w-8 h-8 mb-3 rounded-full border-2 border-muted-foreground/20 border-t-muted-foreground/60 animate-spin" />
|
||||
<Spinner size="xl" className="mb-3" />
|
||||
<p className="text-sm">Waiting for output...</p>
|
||||
<p className="text-xs mt-1 opacity-60">
|
||||
Logs will appear as the server generates output
|
||||
|
||||
@@ -7,7 +7,8 @@ import {
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { GitBranch, ChevronDown, Loader2, CircleDot, Check } from 'lucide-react';
|
||||
import { GitBranch, ChevronDown, CircleDot, Check } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { WorktreeInfo } from '../types';
|
||||
|
||||
@@ -44,7 +45,7 @@ export function WorktreeMobileDropdown({
|
||||
<GitBranch className="w-3.5 h-3.5 shrink-0" />
|
||||
<span className="truncate">{displayBranch}</span>
|
||||
{isActivating ? (
|
||||
<Loader2 className="w-3 h-3 animate-spin shrink-0" />
|
||||
<Spinner size="xs" className="shrink-0" />
|
||||
) : (
|
||||
<ChevronDown className="w-3 h-3 shrink-0 ml-auto" />
|
||||
)}
|
||||
@@ -74,7 +75,7 @@ export function WorktreeMobileDropdown({
|
||||
) : (
|
||||
<div className="w-3.5 h-3.5 shrink-0" />
|
||||
)}
|
||||
{isRunning && <Loader2 className="w-3 h-3 animate-spin shrink-0" />}
|
||||
{isRunning && <Spinner size="xs" className="shrink-0" />}
|
||||
<span className={cn('font-mono text-xs truncate', isSelected && 'font-medium')}>
|
||||
{worktree.branch}
|
||||
</span>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { JSX } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { RefreshCw, Globe, Loader2, CircleDot, GitPullRequest } from 'lucide-react';
|
||||
import { Globe, CircleDot, GitPullRequest } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
|
||||
import type { WorktreeInfo, BranchInfo, DevServerInfo, PRInfo, GitRepoStatus } from '../types';
|
||||
@@ -197,8 +198,8 @@ export function WorktreeTab({
|
||||
aria-label={worktree.branch}
|
||||
data-testid={`worktree-branch-${worktree.branch}`}
|
||||
>
|
||||
{isRunning && <Loader2 className="w-3 h-3 animate-spin" />}
|
||||
{isActivating && !isRunning && <RefreshCw className="w-3 h-3 animate-spin" />}
|
||||
{isRunning && <Spinner size="xs" />}
|
||||
{isActivating && !isRunning && <Spinner size="xs" />}
|
||||
{worktree.branch}
|
||||
{cardCount !== undefined && cardCount > 0 && (
|
||||
<span className="inline-flex items-center justify-center h-4 min-w-[1rem] px-1 text-[10px] font-medium rounded bg-background/80 text-foreground border border-border">
|
||||
@@ -264,8 +265,8 @@ export function WorktreeTab({
|
||||
: 'Click to switch to this branch'
|
||||
}
|
||||
>
|
||||
{isRunning && <Loader2 className="w-3 h-3 animate-spin" />}
|
||||
{isActivating && !isRunning && <RefreshCw className="w-3 h-3 animate-spin" />}
|
||||
{isRunning && <Spinner size="xs" />}
|
||||
{isActivating && !isRunning && <Spinner size="xs" />}
|
||||
{worktree.branch}
|
||||
{cardCount !== undefined && cardCount > 0 && (
|
||||
<span className="inline-flex items-center justify-center h-4 min-w-[1rem] px-1 text-[10px] font-medium rounded bg-background/80 text-foreground border border-border">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useRef, useCallback, useState } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { GitBranch, Plus, RefreshCw } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { cn, pathsEqual } from '@/lib/utils';
|
||||
import { toast } from 'sonner';
|
||||
import { getHttpApiClient } from '@/lib/http-api-client';
|
||||
@@ -285,7 +286,7 @@ export function WorktreePanel({
|
||||
disabled={isLoading}
|
||||
title="Refresh worktrees"
|
||||
>
|
||||
<RefreshCw className={cn('w-3.5 h-3.5', isLoading && 'animate-spin')} />
|
||||
{isLoading ? <Spinner size="xs" /> : <RefreshCw className="w-3.5 h-3.5" />}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
@@ -429,7 +430,7 @@ export function WorktreePanel({
|
||||
disabled={isLoading}
|
||||
title="Refresh worktrees"
|
||||
>
|
||||
<RefreshCw className={cn('w-3.5 h-3.5', isLoading && 'animate-spin')} />
|
||||
{isLoading ? <Spinner size="xs" /> : <RefreshCw className="w-3.5 h-3.5" />}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user