22
33import * as VisuallyHidden from "@radix-ui/react-visually-hidden" ;
44import { Drawer } from "vaul" ;
5- import { styled } from "@pigment-css/react" ;
5+ import { keyframes , styled } from "@pigment-css/react" ;
66import { useTranslations } from "next-intl" ;
77import type { User } from "@supabase/supabase-js" ;
88
@@ -20,6 +20,7 @@ import { SIDEBAR_WIDTH } from "../lib/mapUtils";
2020type MapListingDrawerPanelProps = {
2121 user : User | null ;
2222 selectedListing : SelectedListing | null ;
23+ isSelectedListingLoading : boolean ;
2324 isDesktop : boolean ;
2425 hasTouch : boolean ;
2526 isDrawerHeaderShown : boolean ;
@@ -193,9 +194,42 @@ const NoListingFound = styled("div")(({ theme }) => ({
193194 } ,
194195} ) ) ;
195196
197+ const LoadingState = styled ( "div" ) ( {
198+ display : "flex" ,
199+ flexDirection : "column" ,
200+ gap : "1.5rem" ,
201+ padding : "0 1rem" ,
202+ } ) ;
203+
204+ const mapDrawerPulse = keyframes ( {
205+ "0%" : { opacity : 0.55 } ,
206+ "50%" : { opacity : 1 } ,
207+ "100%" : { opacity : 0.55 } ,
208+ } ) ;
209+
210+ const SkeletonBlock = styled ( "div" ) ( ( { theme } ) => ( {
211+ borderRadius : theme . corners . base ,
212+ background : theme . colors . background . slight ,
213+ opacity : 0.85 ,
214+ animation : `${ mapDrawerPulse } 1.2s ease-in-out infinite` ,
215+ } ) ) ;
216+
217+ const SkeletonHeader = styled ( "div" ) ( {
218+ display : "flex" ,
219+ flexDirection : "column" ,
220+ gap : "0.5rem" ,
221+ } ) ;
222+
223+ const SkeletonText = styled ( "div" ) ( {
224+ display : "flex" ,
225+ flexDirection : "column" ,
226+ gap : "0.75rem" ,
227+ } ) ;
228+
196229export default function MapListingDrawerPanel ( {
197230 user,
198231 selectedListing,
232+ isSelectedListingLoading,
199233 isDesktop,
200234 hasTouch,
201235 isDrawerHeaderShown,
@@ -208,9 +242,10 @@ export default function MapListingDrawerPanel({
208242 const t = useTranslations ( ) ;
209243
210244 const showErrorPanel = isListingError ( selectedListing ) ;
211- const listingForDisplay = isListingError ( selectedListing )
212- ? null
213- : selectedListing ;
245+ const listingForDisplay =
246+ isSelectedListingLoading || isListingError ( selectedListing )
247+ ? null
248+ : selectedListing ;
214249
215250 return (
216251 < Drawer . Portal >
@@ -239,16 +274,25 @@ export default function MapListingDrawerPanel({
239274 } }
240275 >
241276 < StyledHeaderText >
242- < h3 style = { { fontSize : "0.85rem" } } >
243- { listingForDisplay
244- ? getListingDisplayName ( listingForDisplay , user )
245- : "" }
246- </ h3 >
247- < p >
248- { listingForDisplay
249- ? getListingDisplayType ( listingForDisplay )
250- : "" }
251- </ p >
277+ { isSelectedListingLoading ? (
278+ < SkeletonHeader >
279+ < SkeletonBlock style = { { height : "0.85rem" , width : "65%" } } />
280+ < SkeletonBlock style = { { height : "0.8rem" , width : "40%" } } />
281+ </ SkeletonHeader >
282+ ) : (
283+ < >
284+ < h3 style = { { fontSize : "0.85rem" } } >
285+ { listingForDisplay
286+ ? getListingDisplayName ( listingForDisplay , user )
287+ : "" }
288+ </ h3 >
289+ < p >
290+ { listingForDisplay
291+ ? getListingDisplayType ( listingForDisplay )
292+ : "" }
293+ </ p >
294+ </ >
295+ ) }
252296 </ StyledHeaderText >
253297 </ StyledDrawerHeaderInner >
254298
@@ -276,7 +320,20 @@ export default function MapListingDrawerPanel({
276320 </ StyledDrawerHeader >
277321
278322 < StyledDrawerInner >
279- { showErrorPanel ? (
323+ { isSelectedListingLoading ? (
324+ < LoadingState aria-busy = { true } >
325+ < p > { t ( "Map.loadingListing" ) } </ p >
326+ < SkeletonBlock style = { { height : "3rem" , width : "100%" } } />
327+ < SkeletonText >
328+ < SkeletonBlock style = { { height : "1rem" , width : "45%" } } />
329+ < SkeletonBlock style = { { height : "4.5rem" , width : "100%" } } />
330+ < SkeletonBlock style = { { height : "1rem" , width : "35%" } } />
331+ < SkeletonBlock style = { { height : "7rem" , width : "100%" } } />
332+ < SkeletonBlock style = { { height : "1rem" , width : "30%" } } />
333+ < SkeletonBlock style = { { height : "5rem" , width : "100%" } } />
334+ </ SkeletonText >
335+ </ LoadingState >
336+ ) : showErrorPanel ? (
280337 < NoListingFound >
281338 < header >
282339 < h2 > { t ( "Map.emptyTitle" ) } </ h2 >
0 commit comments