11import { WalletAddress } from "@/components/blocks/wallet-address" ;
2- import {
3- GridItem ,
4- SimpleGrid ,
5- Skeleton ,
6- SkeletonText ,
7- useBreakpointValue ,
8- } from "@chakra-ui/react" ;
2+ import { Badge } from "@/components/ui/badge" ;
3+ import { SkeletonContainer } from "@/components/ui/skeleton" ;
4+ import { TrackedLinkTW } from "@/components/ui/tracked-link" ;
95import { ListingStatsV3 } from "contract-ui/tabs/listings/components/listing-stats" ;
106import { useMemo } from "react" ;
117import type { ThirdwebContract } from "thirdweb" ;
@@ -19,7 +15,6 @@ import {
1915} from "thirdweb/extensions/marketplace" ;
2016import { useReadContract } from "thirdweb/react" ;
2117import { min } from "thirdweb/utils" ;
22- import { Badge , Card , Heading , Text , TrackedLink } from "tw-components" ;
2318import { NFTMediaWithEmptyState } from "tw-components/nft-media" ;
2419
2520type ListingData =
@@ -87,18 +82,14 @@ const DirectListingCards: React.FC<ListingCardsSectionProps> = ({
8782 < h2 className = "font-semibold text-2xl tracking-tight" >
8883 Direct Listing
8984 </ h2 >
90- < TrackedLink
85+ < TrackedLinkTW
9186 category = { trackingCategory }
9287 label = "view_all_direct_listings"
93- color = "blue.400"
94- _light = { {
95- color : "blue.600" ,
96- } }
97- gap = { 4 }
88+ className = "text-link-foreground hover:text-foreground"
9889 href = { directListingsHref }
9990 >
10091 View all ->
101- </ TrackedLink >
92+ </ TrackedLinkTW >
10293 </ div >
10394 < ListingCards
10495 listings = { listings }
@@ -151,19 +142,17 @@ const EnglishAuctionCards: React.FC<ListingCardsSectionProps> = ({
151142 return (
152143 < >
153144 < div className = "flex w-full items-center justify-between" >
154- < Heading size = "label.lg" > English Auctions</ Heading >
155- < TrackedLink
145+ < h2 className = "font-semibold text-2xl tracking-tight" >
146+ English Auctions
147+ </ h2 >
148+ < TrackedLinkTW
156149 category = { trackingCategory }
157150 label = "view_all_english_auctions"
158- color = "blue.400"
159- _light = { {
160- color : "blue.600" ,
161- } }
162- gap = { 4 }
151+ className = "text-link-foreground hover:text-foreground"
163152 href = { englishAuctionsHref }
164153 >
165154 View all ->
166- </ TrackedLink >
155+ </ TrackedLinkTW >
167156 </ div >
168157 < ListingCards
169158 listings = { auctions }
@@ -200,15 +189,15 @@ export const MarketplaceDetails: React.FC<MarketplaceDetailsVersionProps> = ({
200189 hasEnglishAuctions = { hasEnglishAuctions }
201190 />
202191
203- { hasDirectListings && contract && (
192+ { hasDirectListings && (
204193 < DirectListingCards
205194 contract = { contract }
206195 trackingCategory = { trackingCategory }
207196 chainSlug = { chainSlug }
208197 />
209198 ) }
210199
211- { hasEnglishAuctions && contract && (
200+ { hasEnglishAuctions && (
212201 < EnglishAuctionCards
213202 contract = { contract }
214203 trackingCategory = { trackingCategory }
@@ -263,82 +252,105 @@ const ListingCards: React.FC<ListingCardsProps> = ({
263252 chainSlug,
264253 contractAddress,
265254} ) => {
266- const isMobile = useBreakpointValue ( { base : true , md : false } ) ;
267-
268255 listings = isPending
269- ? Array . from ( { length : isMobile ? 2 : 3 } ) . map ( ( _ , idx ) =>
270- dummyMetadata ( idx ) ,
271- )
272- : listings . slice ( 0 , isMobile ? 2 : 3 ) ;
256+ ? Array . from ( { length : 3 } ) . map ( ( _ , idx ) => dummyMetadata ( idx ) )
257+ : listings . slice ( 0 , 3 ) ;
273258
274259 const directListingsHref = `/${ chainSlug } /${ contractAddress } /direct-listings` ;
275260 const englishAuctionsHref = `/${ chainSlug } /${ contractAddress } /english-auctions` ;
276261
277262 return (
278- < SimpleGrid gap = { { base : 3 , md : 6 } } columns = { { base : 2 , md : 3 } } >
263+ < div className = "grid grid-cols-2 gap-3 md:grid-cols-3 md:gap-6 max-sm:[&>*:nth-child(n+3)]:hidden" >
279264 { listings . map ( ( listing , index ) => (
280- < GridItem
265+ < div
266+ className = "relative rounded-lg border border-border bg-muted/50 hover:border-foreground hover:bg-muted"
281267 key = { `${ listing . creatorAddress } -${ index } ` }
282- as = { TrackedLink }
283- category = { trackingCategory }
284- href = {
285- listing . type === "direct-listing"
286- ? directListingsHref
287- : englishAuctionsHref
288- }
289- _hover = { { opacity : 0.75 , textDecoration : "none" } }
290268 >
291- < Card p = { 0 } position = "relative" >
292- < div className = "relative aspect-square w-full overflow-hidden rounded-xl" >
293- < Skeleton isLoaded = { ! isPending } >
294- < NFTMediaWithEmptyState
295- metadata = { listing . asset . metadata }
296- requireInteraction
297- width = "100%"
298- height = "100%"
299- />
300- </ Skeleton >
301- </ div >
302- < div className = "flex flex-col gap-1 p-4 pb-3" >
303- < Skeleton w = { ! isPending ? "100%" : "50%" } isLoaded = { ! isPending } >
304- < Heading size = "label.md" > { listing . asset . metadata . name } </ Heading >
305- </ Skeleton >
306- { isMarketplaceV1 && (
307- < SkeletonText isLoaded = { ! isPending } >
308- < Text size = "body.sm" >
309- { listing . type === "direct-listing"
269+ < div className = "relative aspect-square w-full overflow-hidden rounded-lg" >
270+ { /* Image */ }
271+ < SkeletonContainer
272+ loadedData = { isPending ? undefined : listing . asset . metadata }
273+ skeletonData = { listing . asset . metadata }
274+ className = "block h-full w-full"
275+ render = { ( v ) => {
276+ return (
277+ < NFTMediaWithEmptyState
278+ metadata = { v }
279+ requireInteraction
280+ width = "100%"
281+ height = "100%"
282+ />
283+ ) ;
284+ } }
285+ />
286+ </ div >
287+
288+ < div className = "flex flex-col gap-1 p-4 pb-3" >
289+ { /* Card Link + Title */ }
290+ < SkeletonContainer
291+ loadedData = { isPending ? undefined : listing . asset . metadata . name }
292+ skeletonData = "Listing Title"
293+ render = { ( v ) => (
294+ < TrackedLinkTW
295+ category = { trackingCategory }
296+ className = "before:absolute before:inset-0"
297+ href = {
298+ listing . type === "direct-listing"
299+ ? directListingsHref
300+ : englishAuctionsHref
301+ }
302+ >
303+ { v }
304+ </ TrackedLinkTW >
305+ ) }
306+ />
307+
308+ { isMarketplaceV1 && (
309+ < SkeletonContainer
310+ className = "self-start"
311+ loadedData = {
312+ isPending
313+ ? undefined
314+ : listing . type === "direct-listing"
310315 ? "Direct Listing"
311- : "English Auction" }
312- </ Text >
313- </ SkeletonText >
316+ : "English Auction"
317+ }
318+ skeletonData = { listing . type }
319+ render = { ( v ) => (
320+ < p className = "text-muted-foreground text-sm" > { v } </ p >
321+ ) }
322+ />
323+ ) }
324+
325+ < SkeletonContainer
326+ loadedData = { isPending ? undefined : listing . creatorAddress }
327+ skeletonData = { listing . creatorAddress }
328+ className = "mt-4"
329+ render = { ( v ) => (
330+ < div >
331+ < p className = "text-muted-foreground text-sm" > Seller</ p >
332+ < WalletAddress
333+ className = "relative z-[1] self-start"
334+ address = { v }
335+ />
336+ </ div >
314337 ) }
338+ />
315339
316- < Text size = "body.sm" mt = { 4 } >
317- Seller
318- </ Text >
319- < SkeletonText isLoaded = { ! isPending } >
320- < WalletAddress address = { listing . creatorAddress } />
321- </ SkeletonText >
322- < SkeletonText
323- as = { Badge }
324- background = "backgroundHighlight"
325- isLoaded = { ! isPending }
326- skeletonHeight = { 3.5 }
327- noOfLines = { 1 }
328- position = "absolute"
329- rounded = "lg"
330- size = "body.xs"
331- p = { 2 }
332- top = { 2 }
333- right = { 2 }
340+ { ! isPending && (
341+ < Badge
342+ variant = "outline"
343+ className = "absolute top-2 right-2 bg-background py-1.5"
334344 >
335- < b > { listing . currencyValue . displayValue } </ b > { " " }
336- { listing . currencyValue . symbol }
337- </ SkeletonText >
338- </ div >
339- </ Card >
340- </ GridItem >
345+ < p className = "line-clamp-1" >
346+ < b > { listing . currencyValue . displayValue } </ b > { " " }
347+ { listing . currencyValue . symbol }
348+ </ p >
349+ </ Badge >
350+ ) }
351+ </ div >
352+ </ div >
341353 ) ) }
342- </ SimpleGrid >
354+ </ div >
343355 ) ;
344356} ;
0 commit comments