Skip to content

Commit 2653bb4

Browse files
committed
feat(frontend): add skeleton loading state for MCP server selection
1 parent df0d271 commit 2653bb4

File tree

3 files changed

+41
-12
lines changed

3 files changed

+41
-12
lines changed

services/frontend/src/components/mcp-server/wizard/McpServerSelectionStep.vue

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
import { ref, computed, onMounted } from 'vue'
33
import { useI18n } from 'vue-i18n'
44
import { useRouter } from 'vue-router'
5-
import { Loader2, ChevronDown, PackagePlus, AlertTriangle } from 'lucide-vue-next'
5+
import { ChevronDown, PackagePlus, AlertTriangle } from 'lucide-vue-next'
66
import { Button } from '@/components/ui/button'
77
import { Alert, AlertDescription } from '@/components/ui/alert'
8+
import { Skeleton } from '@/components/ui/skeleton'
89
import McpServerSquareCard from '@/components/mcp-server/McpServerSquareCard.vue'
910
import FeaturedMcpServers from '@/components/mcp-server/FeaturedMcpServers.vue'
1011
import PaginationControls from '@/components/ui/pagination/PaginationControls.vue'
@@ -256,9 +257,40 @@ onMounted(() => {
256257
</div>
257258

258259
<!-- Loading State -->
259-
<div v-if="isLoading" class="mt-14 flex items-center justify-center py-8">
260-
<Loader2 class="h-6 w-6 animate-spin mr-2 text-gray-400" />
261-
<span class="text-gray-600">{{ t('messages.loading') }}</span>
260+
<div v-if="isLoading" class="mt-14 space-y-6">
261+
<!-- Skeleton grid with 6 cards (2 rows x 3 columns) -->
262+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
263+
<div v-for="i in 6" :key="i" class="rounded-lg bg-gray-50 border-[6px] border-gray-200 p-6">
264+
<div class="space-y-4">
265+
<!-- Header with avatar and title -->
266+
<div class="flex items-center gap-2">
267+
<Skeleton class="h-8 w-8 rounded-md" />
268+
<Skeleton class="h-5 w-32" />
269+
</div>
270+
<!-- GitHub repo line -->
271+
<div class="flex items-center gap-2 pt-4 border-t border-gray-900/5">
272+
<Skeleton class="h-4 w-4 rounded" />
273+
<Skeleton class="h-4 flex-1" />
274+
</div>
275+
<!-- Description -->
276+
<div class="space-y-2">
277+
<Skeleton class="h-4 w-full" />
278+
<Skeleton class="h-4 w-full" />
279+
<Skeleton class="h-4 w-3/4" />
280+
</div>
281+
<!-- Tags area -->
282+
<div class="flex gap-1.5 flex-wrap min-h-[3rem]">
283+
<Skeleton class="h-6 w-16 rounded-md" />
284+
<Skeleton class="h-6 w-20 rounded-md" />
285+
<Skeleton class="h-6 w-14 rounded-md" />
286+
</div>
287+
<!-- Install button -->
288+
<div class="pt-4 border-t border-gray-900/5">
289+
<Skeleton class="h-10 w-full rounded-md" />
290+
</div>
291+
</div>
292+
</div>
293+
</div>
262294
</div>
263295

264296
<!-- Server Grid (only show when there's a search query and results) -->
Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
<script setup lang="ts">
2-
import type { HTMLAttributes } from 'vue'
3-
import { cn } from '@/lib/utils'
2+
import type { HTMLAttributes } from "vue"
3+
import { cn } from "@/lib/utils"
44
55
interface SkeletonProps {
6-
class?: HTMLAttributes['class']
6+
class?: HTMLAttributes["class"]
77
}
88
99
const props = defineProps<SkeletonProps>()
1010
</script>
1111

1212
<template>
13-
<div
14-
data-slot="skeleton"
15-
:class="cn('animate-pulse rounded-md bg-primary/10', props.class)"
16-
/>
13+
<div :class="cn('animate-pulse rounded-md bg-muted', props.class)" />
1714
</template>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export { default as Skeleton } from './Skeleton.vue'
1+
export { default as Skeleton } from "./Skeleton.vue"

0 commit comments

Comments
 (0)