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

lil ui tweaks

+31 -16
src/components/FaviconIcon.tsx
··· 1 + // FaviconIcon.tsx (Conceptual Component Update) 2 + 1 3 import { useState } from "react"; 2 - import { Globe, Settings as SettingsIcon } from "lucide-react"; 4 + import { Globe } from "lucide-react"; 3 5 4 6 interface FaviconIconProps { 5 7 url: string; 6 8 alt: string; 7 9 className?: string; 10 + useButtonStyling?: boolean; // ⬅️ NEW OPTIONAL PROP 8 11 } 9 12 10 - export default function FaviconIcon({ url, alt, className }: FaviconIconProps) { 13 + export default function FaviconIcon({ 14 + url, 15 + alt, 16 + className, 17 + useButtonStyling = false, 18 + }: FaviconIconProps) { 19 + const [error, setError] = useState(false); 11 20 const [loaded, setLoaded] = useState(false); 12 - const [error, setError] = useState(false); 21 + 22 + // Define the base classes (applied to the image itself) 23 + const imageClasses = "w-full h-full object-contain"; 24 + 25 + // Define the special button classes conditionally 26 + const boundaryClasses = useButtonStyling 27 + ? "bg-white p-1 rounded-full shadow-md flex items-center justify-center" 28 + : ""; // No special styling by default 29 + 30 + // Combine the passed-in class name (for size) with the conditional boundary classes 31 + const finalWrapperClasses = `${className || "w-4 h-4"} ${boundaryClasses}`; 13 32 14 33 if (error) { 15 34 return ( 16 - <Globe 17 - className={ 18 - className || "w-4 h-4 text-neutral-400 dark:text-neutral-500" 19 - } 20 - /> 35 + <div className={`${finalWrapperClasses}`}> 36 + <Globe className={`${imageClasses} text-neutral-500`} /> 37 + </div> 21 38 ); 22 39 } 23 40 24 41 return ( 25 - <> 26 - {/* Fallback/Placeholder */} 42 + // Use the final combined classes on the wrapper 43 + <div className={finalWrapperClasses}> 44 + {/* Placeholder while loading */} 27 45 {!loaded && ( 28 46 <Globe 29 - className={ 30 - className || "w-4 h-4 text-neutral-400 dark:text-neutral-500" 31 - } 47 + className={`${imageClasses} text-neutral-400 dark:text-neutral-500`} 32 48 /> 33 49 )} 34 50 ··· 36 52 <img 37 53 src={url} 38 54 alt={`${alt} favicon`} 39 - className={className || "h-4 w-4"} 40 - // Use inline style to show only when loaded, preventing a broken image icon flicker 55 + className={imageClasses} 41 56 style={{ display: loaded ? "block" : "none" }} 42 57 onLoad={() => { 43 58 setLoaded(true); ··· 47 62 setError(true); 48 63 }} 49 64 /> 50 - </> 65 + </div> 51 66 ); 52 67 }
+3 -3
src/components/HistoryTab.tsx
··· 45 45 <div className="p-6"> 46 46 {/* Setup Assistant Banner - Only show if wizard not completed */} 47 47 {!wizardCompleted && ( 48 - <div className="bg-firefly-banner-dark dark:bg-firefly-banner-dark rounded-2xl p-6 text-white"> 48 + <div className="bg-firefly-banner-dark dark:bg-firefly-banner-dark rounded-2xl p-6 text-white mb-3"> 49 49 <div className="flex flex-col md:flex-row items-start md:items-center justify-between gap-4"> 50 50 <div className="flex-1"> 51 51 <h2 className="text-2xl font-bold mb-2"> ··· 67 67 </div> 68 68 )} 69 69 70 - <div className="flex items-center space-x-3 mt-3 mb-4"> 70 + <div className="flex items-center space-x-3 mb-4"> 71 71 <div> 72 72 <h2 className="text-xl font-bold text-purple-950 dark:text-cyan-50"> 73 73 Previously Uploaded ··· 171 171 <span>{destApp.name}</span> 172 172 </a> 173 173 )} 174 - <div className="flex items-center flex-wrap gap-2"> 174 + <div className="flex items-center flex-wrap gap-2 py-1.5"> 175 175 <span className="text-xs px-2 py-0.5 rounded-full bg-purple-100 dark:bg-slate-900 text-purple-950 dark:text-cyan-50 font-medium"> 176 176 {upload.totalUsers}{" "} 177 177 {upload.totalUsers === 1 ? "user found" : "users found"}
+1 -1
src/components/PlatformSelector.tsx
··· 26 26 title={isEnabled ? `Upload ${p.name} data` : "Coming soon"} 27 27 > 28 28 <PlatformIcon 29 - className={`w-8 h-8 mx-auto mb-2 ${isEnabled ? "text-purple-750 dark:text-cyan-250" : "text-purple-750/50 dark:text-cyan-250/50"}`} 29 + className={`w-6 h-6 mx-auto mb-2 ${isEnabled ? "text-purple-750 dark:text-cyan-250" : "text-purple-750/50 dark:text-cyan-250/50"}`} 30 30 /> 31 31 <div className="text-sm font-medium text-center text-purple-900 dark:text-cyan-100"> 32 32 {p.name}
+12 -10
src/components/SearchResultCard.tsx
··· 118 118 119 119 {/* User Stats and Match Percent */} 120 120 <div className="flex items-center flex-wrap gap-2"> 121 - {match.postCount && match.postCount > 0 && ( 122 - <span className="text-xs px-2 py-0.5 rounded-full bg-purple-100 dark:bg-slate-900 text-purple-950 dark:text-cyan-50 font-medium"> 123 - {match.postCount.toLocaleString()} posts 124 - </span> 125 - )} 126 - {match.followerCount && match.followerCount > 0 && ( 127 - <span className="text-xs px-2 py-0.5 rounded-full bg-purple-100 dark:bg-slate-900 text-purple-950 dark:text-cyan-50 font-medium"> 128 - {match.followerCount.toLocaleString()} followers 129 - </span> 130 - )} 121 + {typeof match.postCount === "number" && 122 + match.postCount > 0 && ( 123 + <span className="text-xs px-2 py-0.5 rounded-full bg-purple-100 dark:bg-slate-900 text-purple-950 dark:text-cyan-50 font-medium"> 124 + {match.postCount.toLocaleString()} posts 125 + </span> 126 + )} 127 + {typeof match.followerCount === "number" && 128 + match.followerCount > 0 && ( 129 + <span className="text-xs px-2 py-0.5 rounded-full bg-purple-100 dark:bg-slate-900 text-purple-950 dark:text-cyan-50 font-medium"> 130 + {match.followerCount.toLocaleString()} followers 131 + </span> 132 + )} 131 133 <span className="text-xs px-2 py-0.5 rounded-full bg-purple-100 dark:bg-slate-900 text-purple-950 dark:text-cyan-50 font-medium"> 132 134 {match.matchScore}% match 133 135 </span>
+5 -5
src/components/UploadTab.tsx
··· 31 31 <div className="p-6"> 32 32 {/* Upload Section */} 33 33 <div className="space-y-3"> 34 - <div className="flex items-center justify-between mb-4"> 35 - <div className="flex items-center space-x-3"> 34 + <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between mb-4"> 35 + <div className="flex items-center space-x-3 mb-2 sm:mb-0"> 36 36 <div> 37 37 <h2 className="text-xl font-bold text-purple-950 dark:text-cyan-50"> 38 38 Upload Following Data ··· 42 42 </p> 43 43 </div> 44 44 </div> 45 - {wizardCompleted && ( 45 + {!wizardCompleted && ( 46 46 <button 47 47 onClick={onShowWizard} 48 - className="text-sm text-orange-650 hover:text-orange-500 dark:text-amber-400 dark:hover:text-amber-300 font-medium transition-colors flex items-center space-x-1" 48 + className="text-md text-orange-650 hover:text-orange-500 dark:text-amber-400 dark:hover:text-amber-300 font-medium transition-colors flex items-center space-x-1" 49 49 > 50 50 <Settings className="w-4 h-4" /> 51 - <span>Reconfigure</span> 51 + <span>Configure</span> 52 52 </button> 53 53 )} 54 54 </div>
+2 -2
src/pages/Loading.tsx
··· 64 64 <div className="max-w-3xl mx-auto px-4 py-6"> 65 65 <div className="flex items-center justify-between"> 66 66 <div className="flex items-center space-x-4"> 67 - <div className="relative w-14 h-14"> 68 - <PlatformIcon className="w-12 h-12" /> 67 + <div className="relative w-12 h-12"> 68 + <PlatformIcon className="w-10 h-10" /> 69 69 </div> 70 70 <div> 71 71 <h2 className="text-xl font-bold">Finding Your Fireflies</h2>
+10 -2
src/pages/Results.tsx
··· 1 1 import { Sparkles, Heart } from "lucide-react"; 2 2 import { PLATFORMS } from "../constants/platforms"; 3 + import { ATPROTO_APPS } from "../constants/atprotoApps"; 3 4 import AppHeader from "../components/AppHeader"; 4 5 import SearchResultCard from "../components/SearchResultCard"; 6 + import FaviconIcon from "../components/FaviconIcon"; 5 7 import type { AtprotoAppId } from "../types/settings"; 6 8 7 9 interface atprotoSession { ··· 73 75 }: ResultsPageProps) { 74 76 const platform = PLATFORMS[sourcePlatform] || PLATFORMS.tiktok; 75 77 const PlatformIcon = platform.icon; 78 + const destinationApp = ATPROTO_APPS[destinationAppId]; 76 79 77 80 return ( 78 81 <div className="min-h-screen pb-24"> ··· 203 206 disabled={isFollowing} 204 207 className="w-full bg-firefly-banner dark:bg-firefly-banner-dark text-white hover:from-amber-600 hover:via-orange-600 hover:to-pink-600 py-5 rounded-2xl font-bold text-lg transition-all shadow-2xl hover:shadow-3xl flex items-center justify-center space-x-3 hover:scale-105 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100" 205 208 > 206 - <Sparkles className="w-6 h-6" /> 209 + <FaviconIcon 210 + url={destinationApp.icon} 211 + alt={destinationApp.name} 212 + className="w-5 h-5" 213 + useButtonStyling={true} 214 + /> 207 215 <span> 208 216 Light Up {totalSelected} Connection 209 - {totalSelected === 1 ? "" : "s"} ✨ 217 + {totalSelected === 1 ? "" : "s"} 210 218 </span> 211 219 </button> 212 220 </div>
+1 -1
src/pages/Settings.tsx
··· 162 162 className="flex items-center justify-between px-3 py-2 rounded-xl transition-colors" 163 163 > 164 164 <div className="flex items-center space-x-3 flex-1"> 165 - <Icon className="w-6 h-6 text-purple-950 dark:text-cyan-50 flex-shrink-0" /> 165 + <Icon className="w-4 h-4 text-purple-950 dark:text-cyan-50 flex-shrink-0" /> 166 166 <div className="flex-1 min-w-0"> 167 167 <div className="font-medium text-purple-950 dark:text-cyan-50"> 168 168 {p.name}