tangled
alpha
login
or
join now
byarielm.fyi
/
atlast
16
fork
atom
ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
16
fork
atom
overview
issues
1
pulls
pipelines
improve loading ui it was so bad
byarielm.fyi
4 months ago
afbe1de2
a62ab972
1/1
deploy.yml
success
3s
+91
-34
1 changed file
expand all
collapse all
unified
split
src
pages
Loading.tsx
+91
-34
src/pages/Loading.tsx
···
1
1
import { Search } from "lucide-react";
2
2
import AppHeader from "../components/AppHeader";
3
3
+
import { PLATFORMS } from "../constants/platforms";
3
4
4
5
interface atprotoSession {
5
6
did: string;
···
24
25
}
25
26
26
27
export default function LoadingPage({ session, onLogout, onNavigate, searchProgress, currentStep }: LoadingPageProps) {
28
28
+
// Default to TikTok styling for loading state
29
29
+
const platform = PLATFORMS.tiktok;
30
30
+
const PlatformIcon = platform.icon;
31
31
+
27
32
return (
28
28
-
<div>
33
33
+
<div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800">
29
34
<AppHeader session={session} onLogout={onLogout} onNavigate={onNavigate} currentStep={currentStep} />
30
30
-
<div className="max-w-3xl mx-auto px-4 py-8">
31
31
-
<div className="bg-white dark:bg-gray-800 rounded-2xl shadow-lg p-8">
32
32
-
<div className="text-center mb-6">
33
33
-
<div className="w-16 h-16 bg-gradient-to-br from-blue-500 to-purple-600 rounded-2xl mx-auto mb-4 flex items-center justify-center">
34
34
-
<Search className="w-8 h-8 text-white animate-pulse" aria-hidden="true" />
35
35
+
36
36
+
{/* Platform Banner - Searching State */}
37
37
+
<div className={`bg-gradient-to-r ${platform.color} text-white`}>
38
38
+
<div className="max-w-3xl mx-auto px-4 py-6">
39
39
+
<div className="flex items-center justify-between">
40
40
+
<div className="flex items-center space-x-4">
41
41
+
<div className="relative">
42
42
+
<PlatformIcon className="w-12 h-12" />
43
43
+
<Search className="w-6 h-6 absolute -bottom-1 -right-1 animate-pulse" aria-hidden="true" />
44
44
+
</div>
45
45
+
<div>
46
46
+
<h2 className="text-xl font-bold">Finding Your People</h2>
47
47
+
<p className="text-white/90 text-sm">
48
48
+
Searching the ATmosphere...
49
49
+
</p>
50
50
+
</div>
35
51
</div>
36
36
-
<h2 className="text-2xl font-bold text-gray-900 dark:text-gray-100 mb-2">Finding Your People</h2>
37
37
-
<p className="text-gray-600 dark:text-gray-300">Searching the ATmosphere for your follows...</p>
52
52
+
{searchProgress.found > 0 && (
53
53
+
<div className="text-right">
54
54
+
<div className="text-2xl font-bold">{searchProgress.found}</div>
55
55
+
<div className="text-xs text-white/80">found</div>
56
56
+
</div>
57
57
+
)}
38
58
</div>
59
59
+
</div>
60
60
+
</div>
39
61
40
40
-
<div className="space-y-4">
41
41
-
<div className="grid grid-cols-3 gap-4 text-center">
42
42
-
<div>
43
43
-
<div className="text-3xl font-bold text-gray-900 dark:text-gray-100" aria-label={`${searchProgress.searched} searched`}>{searchProgress.searched}</div>
44
44
-
<div className="text-sm text-gray-600 dark:text-gray-300">Searched</div>
62
62
+
{/* Progress Stats */}
63
63
+
<div className="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700">
64
64
+
<div className="max-w-3xl mx-auto px-4 py-4">
65
65
+
<div className="grid grid-cols-3 gap-4 text-center mb-4">
66
66
+
<div>
67
67
+
<div className="text-2xl font-bold text-gray-900 dark:text-gray-100" aria-label={`${searchProgress.searched} searched`}>
68
68
+
{searchProgress.searched}
45
69
</div>
46
46
-
<div>
47
47
-
<div className="text-3xl font-bold text-blue-600 dark:text-blue-400" aria-label={`${searchProgress.found} found`}>{searchProgress.found}</div>
48
48
-
<div className="text-sm text-gray-600 dark:text-gray-300">Found</div>
70
70
+
<div className="text-sm text-gray-600 dark:text-gray-300">Searched</div>
71
71
+
</div>
72
72
+
<div>
73
73
+
<div className="text-2xl font-bold text-blue-600 dark:text-blue-400" aria-label={`${searchProgress.found} found`}>
74
74
+
{searchProgress.found}
49
75
</div>
50
50
-
<div>
51
51
-
<div className="text-3xl font-bold text-gray-400 dark:text-gray-500" aria-label={`${searchProgress.total} total`}>{searchProgress.total}</div>
52
52
-
<div className="text-sm text-gray-600 dark:text-gray-300">Total</div>
76
76
+
<div className="text-sm text-gray-600 dark:text-gray-300">Found</div>
77
77
+
</div>
78
78
+
<div>
79
79
+
<div className="text-2xl font-bold text-gray-400 dark:text-gray-500" aria-label={`${searchProgress.total} total`}>
80
80
+
{searchProgress.total}
53
81
</div>
82
82
+
<div className="text-sm text-gray-600 dark:text-gray-300">Total</div>
54
83
</div>
84
84
+
</div>
55
85
56
56
-
<div className="w-full bg-gray-200 w-full bg-gray-200 dark:bg-gray-700 rounded-full h-3" role="progressbar" aria-valuenow={searchProgress.total > 0 ? Math.round((searchProgress.searched / searchProgress.total) * 100) : 0} aria-valuemin={0} aria-valuemax={100}>
57
57
-
<div
58
58
-
className="bg-gradient-to-r from-blue-500 to-purple-600 h-full rounded-full transition-all"
59
59
-
style={{ width: `${searchProgress.total > 0 ? (searchProgress.searched / searchProgress.total) * 100 : 0}%` }}
60
60
-
/>
86
86
+
<div
87
87
+
className="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-3"
88
88
+
role="progressbar"
89
89
+
aria-valuenow={searchProgress.total > 0 ? Math.round((searchProgress.searched / searchProgress.total) * 100) : 0}
90
90
+
aria-valuemin={0}
91
91
+
aria-valuemax={100}
92
92
+
>
93
93
+
<div
94
94
+
className="bg-gradient-to-r from-blue-500 to-purple-600 h-full rounded-full transition-all"
95
95
+
style={{ width: `${searchProgress.total > 0 ? (searchProgress.searched / searchProgress.total) * 100 : 0}%` }}
96
96
+
/>
97
97
+
</div>
98
98
+
</div>
99
99
+
</div>
100
100
+
101
101
+
{/* Skeleton Results - Matches layout of Results page */}
102
102
+
<div className="max-w-3xl mx-auto px-4 py-4 space-y-4">
103
103
+
{[...Array(8)].map((_, i) => (
104
104
+
<div key={i} className="bg-white dark:bg-gray-800 rounded-2xl shadow-sm overflow-hidden animate-pulse">
105
105
+
{/* Source User Skeleton */}
106
106
+
<div className="p-4 bg-gray-50 dark:bg-gray-900 border-b border-gray-200 dark:border-gray-700">
107
107
+
<div className="flex items-center space-x-3">
108
108
+
<div className="w-10 h-10 bg-gray-300 dark:bg-gray-600 rounded-full" />
109
109
+
<div className="flex-1 space-y-2">
110
110
+
<div className="h-4 bg-gray-300 dark:bg-gray-600 rounded w-32" />
111
111
+
<div className="h-3 bg-gray-200 dark:bg-gray-700 rounded w-24" />
112
112
+
</div>
113
113
+
<div className="h-5 w-16 bg-gray-300 dark:bg-gray-600 rounded-full" />
114
114
+
</div>
61
115
</div>
62
62
-
<div className="space-y-3">
63
63
-
{[...Array(5)].map((_, i) => (
64
64
-
<div key={i} className="animate-pulse flex items-center space-x-3 p-4 bg-gray-50 dark:bg-gray-700 rounded-xl">
65
65
-
<div className="w-12 h-12 bg-gray-200 dark:bg-gray-600 rounded-full" />
66
66
-
<div className="flex-1 space-y-2">
67
67
-
<div className="h-4 bg-gray-200 dark:bg-gray-600 rounded w-3/4" />
68
68
-
<div className="h-3 bg-gray-200 dark:bg-gray-600 rounded w-1/2" />
69
69
-
</div>
116
116
+
117
117
+
{/* Match Skeleton */}
118
118
+
<div className="p-4">
119
119
+
<div className="flex items-start space-x-3 p-3 rounded-xl bg-blue-50 dark:bg-blue-900/20">
120
120
+
<div className="w-12 h-12 bg-gray-300 dark:bg-gray-600 rounded-full flex-shrink-0" />
121
121
+
<div className="flex-1 space-y-2">
122
122
+
<div className="h-4 bg-gray-300 dark:bg-gray-600 rounded w-3/4" />
123
123
+
<div className="h-3 bg-gray-200 dark:bg-gray-700 rounded w-1/2" />
124
124
+
<div className="h-3 bg-gray-200 dark:bg-gray-700 rounded w-full" />
125
125
+
<div className="h-5 w-20 bg-green-200 dark:bg-green-900 rounded-full mt-2" />
70
126
</div>
71
71
-
))}
127
127
+
<div className="w-20 h-8 bg-gray-300 dark:bg-gray-600 rounded-full flex-shrink-0" />
128
128
+
</div>
72
129
</div>
73
130
</div>
74
74
-
</div>
131
131
+
))}
75
132
</div>
76
133
</div>
77
134
);