👁️
5
fork

Configure Feed

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

card loading placeholders

+23 -10
+19 -5
src/components/CardImage.tsx
··· 14 14 } from "../lib/scryfall-types"; 15 15 import { type CardFaceType, getImageUri } from "../lib/scryfall-utils"; 16 16 17 + const PLACEHOLDER_STRIPES = `repeating-linear-gradient( 18 + -45deg, 19 + transparent, 20 + transparent 8px, 21 + rgba(0,0,0,0.05) 8px, 22 + rgba(0,0,0,0.05) 16px 23 + )`; 24 + 17 25 interface CardImageProps { 18 26 card: Pick<Card, "name" | "id"> & { layout?: Layout }; 19 27 size?: ImageSize; ··· 77 85 <img 78 86 src={getImageUri(card.id, size, face)} 79 87 alt={card.name} 80 - className={baseClassName} 88 + className={`${baseClassName} bg-gray-200 dark:bg-slate-700`} 89 + style={{ backgroundImage: PLACEHOLDER_STRIPES }} 81 90 loading="lazy" 82 91 /> 83 92 ); ··· 99 108 <img 100 109 src={getImageUri(card.id, size, "front")} 101 110 alt={card.name} 102 - className={baseClassName} 111 + className={`${baseClassName} bg-gray-200 dark:bg-slate-700`} 103 112 loading="lazy" 104 - style={{ backfaceVisibility: "hidden" }} 113 + style={{ 114 + backfaceVisibility: "hidden", 115 + backgroundImage: PLACEHOLDER_STRIPES, 116 + }} 105 117 /> 106 118 <img 107 119 src={getImageUri(card.id, size, "back")} 108 120 alt={`${card.name} (back)`} 109 - className={`${baseClassName} absolute inset-0`} 121 + className={`${baseClassName} bg-gray-200 dark:bg-slate-700 absolute inset-0`} 110 122 loading="lazy" 111 123 style={{ 112 124 backfaceVisibility: "hidden", 113 125 transform: "rotateY(180deg)", 126 + backgroundImage: PLACEHOLDER_STRIPES, 114 127 }} 115 128 /> 116 129 </div> ··· 118 131 <img 119 132 src={getImageUri(card.id, size, face)} 120 133 alt={card.name} 121 - className={`${baseClassName} motion-safe:transition-transform motion-safe:duration-500 motion-safe:ease-in-out`} 134 + className={`${baseClassName} bg-gray-200 dark:bg-slate-700 motion-safe:transition-transform motion-safe:duration-500 motion-safe:ease-in-out`} 122 135 loading="lazy" 123 136 style={{ 137 + backgroundImage: PLACEHOLDER_STRIPES, 124 138 transformOrigin: "center center", 125 139 transform: isFlipped 126 140 ? flipBehavior === "rotate90"
+4 -5
src/routes/profile/$did/index.tsx
··· 2 2 import { useQuery, useSuspenseQuery } from "@tanstack/react-query"; 3 3 import { createFileRoute, Link } from "@tanstack/react-router"; 4 4 import { useMemo } from "react"; 5 + import { CardImage } from "@/components/CardImage"; 5 6 import { ClientDate } from "@/components/ClientDate"; 6 7 import { asRkey, type DeckRecordResponse } from "@/lib/atproto-client"; 7 8 import { listUserDecksQueryOptions } from "@/lib/deck-queries"; 8 9 import { didDocumentQueryOptions, extractHandle } from "@/lib/did-to-handle"; 9 10 import { formatDisplayName } from "@/lib/format-utils"; 10 11 import type { ScryfallId } from "@/lib/scryfall-types"; 11 - import { getImageUri } from "@/lib/scryfall-utils"; 12 12 import { useAuth } from "@/lib/useAuth"; 13 13 14 14 type SortOption = "updated-desc" | "updated-asc" | "name-asc" | "name-desc"; ··· 290 290 {/* Thumbnail */} 291 291 {thumbnailId && ( 292 292 <div className="flex-shrink-0 w-16 h-[90px] rounded overflow-hidden"> 293 - <img 294 - src={getImageUri(thumbnailId, "small")} 295 - alt="" 293 + <CardImage 294 + card={{ id: thumbnailId, name: record.value.name }} 295 + size="small" 296 296 className="w-full h-full object-cover" 297 - loading="lazy" 298 297 /> 299 298 </div> 300 299 )}