diff --git a/apps/frontend/src/renderer/components/CreateSpecView.tsx b/apps/frontend/src/renderer/components/CreateSpecView.tsx
index 384468b8b..e051874b3 100644
--- a/apps/frontend/src/renderer/components/CreateSpecView.tsx
+++ b/apps/frontend/src/renderer/components/CreateSpecView.tsx
@@ -44,6 +44,11 @@ import { cn } from '../lib/utils';
import type { PatternSuggestion } from '../../shared/types';
export type { PatternSuggestion };
+/**
+ * Import skeleton component for loading state
+ */
+import { PatternSuggestionsSkeleton } from './skeletons/PatternSuggestionsSkeleton';
+
/**
* Pattern action state
*/
@@ -440,16 +445,7 @@ export function CreateSpecView({
{/* Loading State */}
- {isLoading && (
-
-
-
-
-
Finding relevant patterns...
-
-
-
- )}
+ {isLoading && }
{/* Error State */}
{error && (
diff --git a/apps/frontend/src/renderer/components/skeletons/PatternSuggestionsSkeleton.tsx b/apps/frontend/src/renderer/components/skeletons/PatternSuggestionsSkeleton.tsx
new file mode 100644
index 000000000..fe805b30f
--- /dev/null
+++ b/apps/frontend/src/renderer/components/skeletons/PatternSuggestionsSkeleton.tsx
@@ -0,0 +1,110 @@
+import { Card, CardContent, CardHeader } from '../ui/card';
+
+interface PatternSuggestionsSkeletonProps {
+ /** Number of pattern cards to render */
+ count?: number;
+ /** Whether to show header section */
+ showHeader?: boolean;
+}
+
+/**
+ * Skeleton loader for PatternSuggestions in CreateSpecView
+ * Matches the structure: header with badges, pattern cards with category badges,
+ * confidence levels, pattern text, action buttons, and expandable details
+ */
+export function PatternSuggestionsSkeleton({
+ count = 3,
+ showHeader = true
+}: PatternSuggestionsSkeletonProps) {
+ return (
+
+ {/* Header Section */}
+ {showHeader && (
+
+
+ {/* Title with icon */}
+
+ {/* Subtitle */}
+
+
+ {/* Summary badges */}
+
+
+ )}
+
+ {/* Pattern Cards */}
+
+ {Array.from({ length: count }).map((_, index) => (
+
+
+
+ {/* Main content area */}
+
+ {/* Category Badge and Confidence Level */}
+
+
+ {/* Pattern Text Lines */}
+
+
+
+ {index % 2 === 0 && (
+
+ )}
+
+
+
+ {/* Action Buttons */}
+
+
+
+
+
+ {/* Expandable Details Section */}
+
+ {/* "Show details" button placeholder */}
+
+
+ {/* Details content (simulate expanded state ~50% of the time) */}
+ {index % 2 === 0 && (
+
+ {/* Reasoning line */}
+
+
+ {/* Metadata row */}
+
+
+ )}
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/apps/frontend/src/renderer/components/skeletons/SpecDetailSkeleton.tsx b/apps/frontend/src/renderer/components/skeletons/SpecDetailSkeleton.tsx
new file mode 100644
index 000000000..3b44acd56
--- /dev/null
+++ b/apps/frontend/src/renderer/components/skeletons/SpecDetailSkeleton.tsx
@@ -0,0 +1,108 @@
+import { Card } from '../ui/card';
+
+interface SpecDetailSkeletonProps {
+ /** Number of phase skeletons to render */
+ phaseCount?: number;
+ /** Whether to show description placeholder */
+ showDescription?: boolean;
+}
+
+/**
+ * Skeleton loader for SpecDetail/TaskOverview implementation plan
+ * Matches the structure: section header, phases, subtasks, metadata
+ */
+export function SpecDetailSkeleton({ phaseCount = 3, showDescription = true }: SpecDetailSkeletonProps) {
+ return (
+
+ {/* Section Header */}
+
+
+ {/* Optional Description */}
+ {showDescription && (
+
+ )}
+
+ {/* Phases */}
+
+ {Array.from({ length: phaseCount }).map((_, phaseIndex) => (
+
+ {/* Phase Header */}
+
+ {/* Chevron placeholder */}
+
+
+ {/* Status icon placeholder */}
+
+
+ {/* Phase title and badge */}
+
+
+
+ {/* Progress text */}
+
+
+
+
+ {/* Subtasks (simulate expanded phase) */}
+
+ {/* Separator */}
+
+
+ {/* Subtask items */}
+ {Array.from({ length: 3 + (phaseIndex % 2) }).map((_, subtaskIndex) => (
+
+ {/* Status badge placeholder */}
+
+
+ {/* Subtask content */}
+
+ {/* Subtask description */}
+
+ {/* Verification text (optional) */}
+ {subtaskIndex % 2 === 0 && (
+
+ )}
+
+
+ ))}
+
+
+ ))}
+
+
+ {/* QA Report Section (skeleton) */}
+
+ {/* QA Report header */}
+
+
+ {/* QA content lines */}
+
+
+
+ );
+}
diff --git a/apps/frontend/src/renderer/components/skeletons/index.ts b/apps/frontend/src/renderer/components/skeletons/index.ts
new file mode 100644
index 000000000..9f13550dd
--- /dev/null
+++ b/apps/frontend/src/renderer/components/skeletons/index.ts
@@ -0,0 +1,7 @@
+export { ChangelogSkeleton } from './ChangelogSkeleton';
+export { IssueListSkeleton } from './IssueListSkeleton';
+export { PRListSkeleton } from './PRListSkeleton';
+export { ProjectListSkeleton } from './ProjectListSkeleton';
+export { TaskCardSkeleton } from './TaskCardSkeleton';
+export { SpecDetailSkeleton } from './SpecDetailSkeleton';
+export { PatternSuggestionsSkeleton } from './PatternSuggestionsSkeleton';
diff --git a/apps/frontend/src/renderer/components/task-detail/TaskOverview.tsx b/apps/frontend/src/renderer/components/task-detail/TaskOverview.tsx
index 8e4dbc36a..f87108be6 100644
--- a/apps/frontend/src/renderer/components/task-detail/TaskOverview.tsx
+++ b/apps/frontend/src/renderer/components/task-detail/TaskOverview.tsx
@@ -16,6 +16,7 @@ import {
import { Badge } from '../ui/badge';
import { Separator } from '../ui/separator';
import { ScrollArea } from '../ui/scroll-area';
+import { SpecDetailSkeleton } from '../skeletons/SpecDetailSkeleton';
import { cn } from '../../lib/utils';
import type { Task, ImplementationPlan, Phase, SubtaskStatus, QAEscalation } from '../../../shared/types';
@@ -124,11 +125,7 @@ export function TaskOverview({ task }: TaskOverviewProps) {
};
if (isLoading) {
- return (
-
-
-
- );
+ return ;
}
if (error) {