Skip to content

Commit 0c72232

Browse files
authored
feat: add loading animation to mcp cards (#433)
1 parent 39cd1b8 commit 0c72232

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

renderer/src/features/mcp-servers/components/card-mcp-server.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,18 +164,30 @@ export function CardMcpServer({
164164

165165
// Check if the server is in deleting state
166166
const isDeleting = isDeletePending || status === 'deleting'
167+
const isTransitioning =
168+
status === 'starting' || status === 'stopping' || status === 'restarting'
169+
const isStopped = status === 'stopped' || status === 'stopping'
167170

168171
return (
169172
<Card
170173
className={twMerge(
171-
'transition-[color,box-shadow,opacity]',
174+
'transition-all duration-300 ease-in-out',
172175
isNewServer ? 'ring-2' : undefined,
173-
isDeleting ? 'pointer-events-none opacity-50' : undefined
176+
isDeleting ? 'pointer-events-none opacity-50' : undefined,
177+
isTransitioning && 'animate-diagonal-ring',
178+
isStopped && 'bg-card/65'
174179
)}
175180
>
176181
<CardHeader>
177182
<div className="flex items-center justify-between">
178-
<CardTitle className="flex items-center text-xl">{name}</CardTitle>
183+
<CardTitle
184+
className={twMerge(
185+
'flex items-center text-xl',
186+
isStopped && 'text-primary/65'
187+
)}
188+
>
189+
{name}
190+
</CardTitle>
179191
<DropdownMenu>
180192
<DropdownMenuTrigger asChild>
181193
<Button

renderer/src/index.css

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,53 @@
176176
.app-region-no-drag {
177177
app-region: no-drag;
178178
}
179+
180+
@keyframes diagonal-ring {
181+
from {
182+
background-position: -150% -150%;
183+
}
184+
185+
to {
186+
background-position: 150% 150%;
187+
}
188+
}
189+
190+
.animate-diagonal-ring {
191+
position: relative;
192+
}
193+
194+
.animate-diagonal-ring::before {
195+
content: '';
196+
position: absolute;
197+
inset: 0;
198+
padding: 1px;
199+
/* ring thickness */
200+
border-radius: inherit;
201+
pointer-events: none;
202+
203+
/* using card foreground color with reduced opacity */
204+
background: linear-gradient(
205+
120deg,
206+
transparent 0%,
207+
transparent 40%,
208+
color-mix(in oklch, var(--card-foreground) 25%, transparent) 50%,
209+
transparent 60%,
210+
transparent 100%
211+
);
212+
background-size: 300% 300%;
213+
animation: diagonal-ring 5s linear infinite;
214+
215+
/* show only the ring */
216+
-webkit-mask:
217+
linear-gradient(#fff 0 0) content-box,
218+
linear-gradient(#fff 0 0) padding-box;
219+
-webkit-mask-composite: xor;
220+
mask-composite: exclude;
221+
}
222+
223+
@media (prefers-reduced-motion: reduce) {
224+
.animate-diagonal-ring::before {
225+
animation: none;
226+
}
227+
}
179228
}

0 commit comments

Comments
 (0)