The weeb for the next gen discord boat - Wamellow wamellow.com
bot discord
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(profile): skeleton loader (#42)

authored by

Luna Seemann and committed by
GitHub
ce06602e 99278579

+27 -18
+12 -9
app/profile/connections/page.tsx
··· 2 2 3 3 import { ControlledInput } from "@/components/inputs/controlled-input"; 4 4 import Modal from "@/components/modal"; 5 - import Notice, { NoticeType } from "@/components/notice"; 6 5 import { ScreenMessage } from "@/components/screen-message"; 7 6 import { Button } from "@/components/ui/button"; 7 + import { Skeleton } from "@/components/ui/skeleton"; 8 8 import { useApi } from "@/lib/api/hook"; 9 9 import { type ApiV1UsersMeConnectionsGetResponse, ConnectionType } from "@/typings"; 10 10 import { cn } from "@/utils/cn"; ··· 27 27 return <ScreenMessage description={error} />; 28 28 } 29 29 30 - if (isLoading || !data) return <></>; 30 + if (isLoading || !data) { 31 + return ( 32 + <div className="space-y-2"> 33 + {CONNECTION_TYPES.map(([, type]) => ( 34 + <Skeleton key={type} className="w-full rounded-xl h-21" isLoading={true} /> 35 + ))} 36 + </div> 37 + ); 38 + } 31 39 32 40 return ( 33 41 <div className="space-y-2"> 34 - <Notice 35 - type={NoticeType.Info} 36 - message="This is still in testing, don&apos;t expect it to work properly yet!" 37 - /> 38 - 39 42 {CONNECTION_TYPES.map(([name, type]) => ( 40 43 <Connection key={name} name={name} type={type} data={data} /> 41 44 ))} ··· 58 61 {connection 59 62 ? <Image 60 63 alt={`user's ${name} avatar`} 61 - className="rounded-full size-12 shrink-0" 64 + className="rounded-full size-13 shrink-0" 62 65 height={56} 63 66 src={connection?.avatar || "/discord.webp"} 64 67 width={56} 65 68 /> 66 69 : ( 67 - <div className="bg-wamellow-100 rounded-full size-12 flex items-center justify-center text-neutral-300 shrink-0"> 70 + <div className="bg-wamellow-100 rounded-full size-13 flex items-center justify-center text-neutral-300 shrink-0"> 68 71 <Icon type={type} /> 69 72 </div> 70 73 )
+15 -9
app/profile/page.tsx
··· 4 4 import { ControlledInput } from "@/components/inputs/controlled-input"; 5 5 import { ScreenMessage } from "@/components/screen-message"; 6 6 import { Button } from "@/components/ui/button"; 7 + import { Skeleton } from "@/components/ui/skeleton"; 7 8 import { useApi } from "@/lib/api/hook"; 8 9 import type { ApiV1UsersMeGuildsGetResponse } from "@/typings"; 9 10 import { cn } from "@/utils/cn"; ··· 39 40 [data, search] 40 41 ); 41 42 42 - const isHuge = Array.isArray(data) && data.length > MAX_GUILDS; 43 + const size = Array.isArray(data) ? data.length : 0; 44 + const isHuge = size > MAX_GUILDS; 43 45 44 46 if (error) { 45 47 return ( ··· 49 51 /> 50 52 ); 51 53 } 52 - 53 - if (isLoading || !data) return <></>; 54 54 55 55 return (<div className="flex flex-col w-full"> 56 - 57 56 <div className="flex flex-col md:flex-row md:justify-between gap-2"> 58 57 <ControlledInput 59 58 thin ··· 91 90 </div> 92 91 </div> 93 92 94 - {!isLoading && ( 93 + {isLoading ? ( 94 + <div className="grid grid-cols-1 gap-3.5 w-full mt-3 lg:grid-cols-3 md:grid-cols-2"> 95 + {Array.from({ length: 1 }).map((_, i) => ( 96 + <Skeleton key={i} className="h-22 rounded-xl" style={{ opacity: 1 / i }} /> 97 + ))} 98 + </div> 99 + ) : ( 95 100 <motion.ul 96 101 variants={{ 97 102 hidden: { opacity: 1, scale: 0 }, ··· 99 104 opacity: 1, 100 105 scale: 1, 101 106 transition: { 102 - delayChildren: data.length > 20 ? 0.2 : 0.3, 103 - staggerChildren: data.length > 20 ? 0.1 : 0.2 107 + delayChildren: size > 20 ? 0.2 : 0.3, 108 + staggerChildren: size > 20 ? 0.1 : 0.2 104 109 } 105 110 } 106 111 }} ··· 121 126 122 127 {isHuge && ( 123 128 <ScreenMessage 129 + top="5rem" 124 130 title="There are too many servers.." 125 - description={`To save some performance, use the search to find a guild. Showing ${MAX_GUILDS} out of ~${data.length < 1_000 ? data.length : Math.round(data.length / 1_000) * 1_000}.`} 131 + description={`To save some performance, use the search to find a guild. Showing ${MAX_GUILDS} out of ~${size < 1_000 ? size : Math.round(size / 1_000) * 1_000}.`} 126 132 /> 127 133 )} 128 - </div>); 134 + </div >); 129 135 } 130 136 131 137 function sort(a: ApiV1UsersMeGuildsGetResponse, b: ApiV1UsersMeGuildsGetResponse) {