ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto

improve loading ui it was so bad

Changed files
+91 -34
src
pages
+91 -34
src/pages/Loading.tsx
··· 1 1 import { Search } from "lucide-react"; 2 2 import AppHeader from "../components/AppHeader"; 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 + // Default to TikTok styling for loading state 29 + const platform = PLATFORMS.tiktok; 30 + const PlatformIcon = platform.icon; 31 + 27 32 return ( 28 - <div> 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 - <div className="max-w-3xl mx-auto px-4 py-8"> 31 - <div className="bg-white dark:bg-gray-800 rounded-2xl shadow-lg p-8"> 32 - <div className="text-center mb-6"> 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 - <Search className="w-8 h-8 text-white animate-pulse" aria-hidden="true" /> 35 + 36 + {/* Platform Banner - Searching State */} 37 + <div className={`bg-gradient-to-r ${platform.color} text-white`}> 38 + <div className="max-w-3xl mx-auto px-4 py-6"> 39 + <div className="flex items-center justify-between"> 40 + <div className="flex items-center space-x-4"> 41 + <div className="relative"> 42 + <PlatformIcon className="w-12 h-12" /> 43 + <Search className="w-6 h-6 absolute -bottom-1 -right-1 animate-pulse" aria-hidden="true" /> 44 + </div> 45 + <div> 46 + <h2 className="text-xl font-bold">Finding Your People</h2> 47 + <p className="text-white/90 text-sm"> 48 + Searching the ATmosphere... 49 + </p> 50 + </div> 35 51 </div> 36 - <h2 className="text-2xl font-bold text-gray-900 dark:text-gray-100 mb-2">Finding Your People</h2> 37 - <p className="text-gray-600 dark:text-gray-300">Searching the ATmosphere for your follows...</p> 52 + {searchProgress.found > 0 && ( 53 + <div className="text-right"> 54 + <div className="text-2xl font-bold">{searchProgress.found}</div> 55 + <div className="text-xs text-white/80">found</div> 56 + </div> 57 + )} 38 58 </div> 59 + </div> 60 + </div> 39 61 40 - <div className="space-y-4"> 41 - <div className="grid grid-cols-3 gap-4 text-center"> 42 - <div> 43 - <div className="text-3xl font-bold text-gray-900 dark:text-gray-100" aria-label={`${searchProgress.searched} searched`}>{searchProgress.searched}</div> 44 - <div className="text-sm text-gray-600 dark:text-gray-300">Searched</div> 62 + {/* Progress Stats */} 63 + <div className="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700"> 64 + <div className="max-w-3xl mx-auto px-4 py-4"> 65 + <div className="grid grid-cols-3 gap-4 text-center mb-4"> 66 + <div> 67 + <div className="text-2xl font-bold text-gray-900 dark:text-gray-100" aria-label={`${searchProgress.searched} searched`}> 68 + {searchProgress.searched} 45 69 </div> 46 - <div> 47 - <div className="text-3xl font-bold text-blue-600 dark:text-blue-400" aria-label={`${searchProgress.found} found`}>{searchProgress.found}</div> 48 - <div className="text-sm text-gray-600 dark:text-gray-300">Found</div> 70 + <div className="text-sm text-gray-600 dark:text-gray-300">Searched</div> 71 + </div> 72 + <div> 73 + <div className="text-2xl font-bold text-blue-600 dark:text-blue-400" aria-label={`${searchProgress.found} found`}> 74 + {searchProgress.found} 49 75 </div> 50 - <div> 51 - <div className="text-3xl font-bold text-gray-400 dark:text-gray-500" aria-label={`${searchProgress.total} total`}>{searchProgress.total}</div> 52 - <div className="text-sm text-gray-600 dark:text-gray-300">Total</div> 76 + <div className="text-sm text-gray-600 dark:text-gray-300">Found</div> 77 + </div> 78 + <div> 79 + <div className="text-2xl font-bold text-gray-400 dark:text-gray-500" aria-label={`${searchProgress.total} total`}> 80 + {searchProgress.total} 53 81 </div> 82 + <div className="text-sm text-gray-600 dark:text-gray-300">Total</div> 54 83 </div> 84 + </div> 55 85 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 - <div 58 - className="bg-gradient-to-r from-blue-500 to-purple-600 h-full rounded-full transition-all" 59 - style={{ width: `${searchProgress.total > 0 ? (searchProgress.searched / searchProgress.total) * 100 : 0}%` }} 60 - /> 86 + <div 87 + className="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-3" 88 + role="progressbar" 89 + aria-valuenow={searchProgress.total > 0 ? Math.round((searchProgress.searched / searchProgress.total) * 100) : 0} 90 + aria-valuemin={0} 91 + aria-valuemax={100} 92 + > 93 + <div 94 + className="bg-gradient-to-r from-blue-500 to-purple-600 h-full rounded-full transition-all" 95 + style={{ width: `${searchProgress.total > 0 ? (searchProgress.searched / searchProgress.total) * 100 : 0}%` }} 96 + /> 97 + </div> 98 + </div> 99 + </div> 100 + 101 + {/* Skeleton Results - Matches layout of Results page */} 102 + <div className="max-w-3xl mx-auto px-4 py-4 space-y-4"> 103 + {[...Array(8)].map((_, i) => ( 104 + <div key={i} className="bg-white dark:bg-gray-800 rounded-2xl shadow-sm overflow-hidden animate-pulse"> 105 + {/* Source User Skeleton */} 106 + <div className="p-4 bg-gray-50 dark:bg-gray-900 border-b border-gray-200 dark:border-gray-700"> 107 + <div className="flex items-center space-x-3"> 108 + <div className="w-10 h-10 bg-gray-300 dark:bg-gray-600 rounded-full" /> 109 + <div className="flex-1 space-y-2"> 110 + <div className="h-4 bg-gray-300 dark:bg-gray-600 rounded w-32" /> 111 + <div className="h-3 bg-gray-200 dark:bg-gray-700 rounded w-24" /> 112 + </div> 113 + <div className="h-5 w-16 bg-gray-300 dark:bg-gray-600 rounded-full" /> 114 + </div> 61 115 </div> 62 - <div className="space-y-3"> 63 - {[...Array(5)].map((_, i) => ( 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 - <div className="w-12 h-12 bg-gray-200 dark:bg-gray-600 rounded-full" /> 66 - <div className="flex-1 space-y-2"> 67 - <div className="h-4 bg-gray-200 dark:bg-gray-600 rounded w-3/4" /> 68 - <div className="h-3 bg-gray-200 dark:bg-gray-600 rounded w-1/2" /> 69 - </div> 116 + 117 + {/* Match Skeleton */} 118 + <div className="p-4"> 119 + <div className="flex items-start space-x-3 p-3 rounded-xl bg-blue-50 dark:bg-blue-900/20"> 120 + <div className="w-12 h-12 bg-gray-300 dark:bg-gray-600 rounded-full flex-shrink-0" /> 121 + <div className="flex-1 space-y-2"> 122 + <div className="h-4 bg-gray-300 dark:bg-gray-600 rounded w-3/4" /> 123 + <div className="h-3 bg-gray-200 dark:bg-gray-700 rounded w-1/2" /> 124 + <div className="h-3 bg-gray-200 dark:bg-gray-700 rounded w-full" /> 125 + <div className="h-5 w-20 bg-green-200 dark:bg-green-900 rounded-full mt-2" /> 70 126 </div> 71 - ))} 127 + <div className="w-20 h-8 bg-gray-300 dark:bg-gray-600 rounded-full flex-shrink-0" /> 128 + </div> 72 129 </div> 73 130 </div> 74 - </div> 131 + ))} 75 132 </div> 76 133 </div> 77 134 );