Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol. wisp.place

lets try skeletons again

Changed files
+101 -6
public
components
editor
styles
+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
··· 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
··· 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
··· 178 178 animation: arrow-bounce 1.5s ease-in-out infinite; 179 179 } 180 180 181 + @keyframes shimmer { 182 + 100% { 183 + transform: translateX(100%); 184 + } 185 + } 186 + 181 187 /* Shiki syntax highlighting styles */ 182 188 .shiki-wrapper { 183 189 border-radius: 0.5rem;