+31
public/components/ui/skeleton.tsx
+31
public/components/ui/skeleton.tsx
···
1
+
import { cn } from '@public/lib/utils'
2
+
3
+
interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement> {}
4
+
5
+
function Skeleton({ className, ...props }: SkeletonProps) {
6
+
return (
7
+
<div
8
+
className={cn(
9
+
'animate-pulse rounded-md bg-muted',
10
+
className
11
+
)}
12
+
{...props}
13
+
/>
14
+
)
15
+
}
16
+
17
+
interface SkeletonShimmerProps extends React.HTMLAttributes<HTMLDivElement> {}
18
+
19
+
function SkeletonShimmer({ className, ...props }: SkeletonShimmerProps) {
20
+
return (
21
+
<div
22
+
className={cn(
23
+
'relative overflow-hidden rounded-md bg-muted before:absolute before:inset-0 before:-translate-x-full before:animate-[shimmer_2s_infinite] before:bg-gradient-to-r before:from-transparent before:via-white/10 before:to-transparent',
24
+
className
25
+
)}
26
+
{...props}
27
+
/>
28
+
)
29
+
}
30
+
31
+
export { Skeleton, SkeletonShimmer }
+47
-4
public/editor/tabs/DomainsTab.tsx
+47
-4
public/editor/tabs/DomainsTab.tsx
···
10
10
import { Input } from '@public/components/ui/input'
11
11
import { Label } from '@public/components/ui/label'
12
12
import { Badge } from '@public/components/ui/badge'
13
+
import { SkeletonShimmer } from '@public/components/ui/skeleton'
13
14
import {
14
15
Dialog,
15
16
DialogContent,
···
128
129
</CardHeader>
129
130
<CardContent>
130
131
{domainsLoading ? (
131
-
<div className="flex items-center justify-center py-4">
132
-
<Loader2 className="w-6 h-6 animate-spin text-muted-foreground" />
132
+
<div className="space-y-4">
133
+
<div className="space-y-2">
134
+
{[...Array(2)].map((_, i) => (
135
+
<div
136
+
key={i}
137
+
className="flex items-center justify-between p-3 border border-border rounded-lg"
138
+
>
139
+
<div className="flex flex-col gap-2 flex-1">
140
+
<div className="flex items-center gap-2">
141
+
<SkeletonShimmer className="h-4 w-4 rounded-full" />
142
+
<SkeletonShimmer className="h-4 w-40" />
143
+
</div>
144
+
<SkeletonShimmer className="h-3 w-32 ml-6" />
145
+
</div>
146
+
<SkeletonShimmer className="h-8 w-8" />
147
+
</div>
148
+
))}
149
+
</div>
150
+
<div className="p-4 bg-muted/30 rounded-lg space-y-3">
151
+
<SkeletonShimmer className="h-4 w-full" />
152
+
<div className="space-y-2">
153
+
<SkeletonShimmer className="h-4 w-24" />
154
+
<SkeletonShimmer className="h-10 w-full" />
155
+
</div>
156
+
<SkeletonShimmer className="h-10 w-full" />
157
+
</div>
133
158
</div>
134
159
) : (
135
160
<div className="space-y-4">
···
262
287
</Button>
263
288
264
289
{domainsLoading ? (
265
-
<div className="flex items-center justify-center py-4">
266
-
<Loader2 className="w-6 h-6 animate-spin text-muted-foreground" />
290
+
<div className="space-y-2">
291
+
{[...Array(2)].map((_, i) => (
292
+
<div
293
+
key={i}
294
+
className="flex items-center justify-between p-3 border border-border rounded-lg"
295
+
>
296
+
<div className="flex flex-col gap-2 flex-1">
297
+
<div className="flex items-center gap-2">
298
+
<SkeletonShimmer className="h-4 w-4 rounded-full" />
299
+
<SkeletonShimmer className="h-4 w-48" />
300
+
</div>
301
+
<SkeletonShimmer className="h-3 w-36 ml-6" />
302
+
</div>
303
+
<div className="flex items-center gap-2">
304
+
<SkeletonShimmer className="h-8 w-20" />
305
+
<SkeletonShimmer className="h-8 w-20" />
306
+
<SkeletonShimmer className="h-8 w-8" />
307
+
</div>
308
+
</div>
309
+
))}
267
310
</div>
268
311
) : customDomains.length === 0 ? (
269
312
<div className="text-center py-4 text-muted-foreground text-sm">
+17
-2
public/editor/tabs/SitesTab.tsx
+17
-2
public/editor/tabs/SitesTab.tsx
···
7
7
} from '@public/components/ui/card'
8
8
import { Button } from '@public/components/ui/button'
9
9
import { Badge } from '@public/components/ui/badge'
10
+
import { SkeletonShimmer } from '@public/components/ui/skeleton'
10
11
import {
11
12
Globe,
12
13
ExternalLink,
···
84
85
</CardHeader>
85
86
<CardContent className="space-y-4">
86
87
{sitesLoading ? (
87
-
<div className="flex items-center justify-center py-8">
88
-
<Loader2 className="w-6 h-6 animate-spin text-muted-foreground" />
88
+
<div className="space-y-4">
89
+
{[...Array(3)].map((_, i) => (
90
+
<div
91
+
key={i}
92
+
className="flex items-center justify-between p-4 border border-border rounded-lg"
93
+
>
94
+
<div className="flex-1 space-y-3">
95
+
<div className="flex items-center gap-3">
96
+
<SkeletonShimmer className="h-6 w-48" />
97
+
<SkeletonShimmer className="h-5 w-16" />
98
+
</div>
99
+
<SkeletonShimmer className="h-4 w-64" />
100
+
</div>
101
+
<SkeletonShimmer className="h-9 w-28" />
102
+
</div>
103
+
))}
89
104
</div>
90
105
) : sites.length === 0 ? (
91
106
<div className="text-center py-8 text-muted-foreground">
+6
public/styles/global.css
+6
public/styles/global.css