mirror of
				https://github.com/walkxcode/dashboard-icons.git
				synced 2025-10-31 08:47:57 +01:00 
			
		
		
		
	feat(icon-card): Add loading state and WebP support for images
This commit is contained in:
		| @@ -3,6 +3,7 @@ import { BASE_URL } from "@/constants" | ||||
| import type { Icon } from "@/types/icons" | ||||
| import Image from "next/image" | ||||
| import Link from "next/link" | ||||
| import { useState } from "react" | ||||
|  | ||||
| export function IconCard({ | ||||
| 	name, | ||||
| @@ -13,16 +14,34 @@ export function IconCard({ | ||||
| 	data: Icon | ||||
| 	matchedAlias?: string | ||||
| }) { | ||||
| 	const [isLoading, setIsLoading] = useState(true) | ||||
|  | ||||
| 	// Construct URLs for both WebP and the original format | ||||
| 	const webpSrc = `${BASE_URL}/webp/${name}.webp` | ||||
| 	const originalSrc = `${BASE_URL}/${iconData.base}/${name}.${iconData.base}` | ||||
|  | ||||
| 	return ( | ||||
| 		<MagicCard className="rounded-md shadow-md"> | ||||
| 			<Link prefetch={false} href={`/icons/${name}`} className="group flex flex-col items-center p-3 sm:p-4 cursor-pointer"> | ||||
| 				<div className="relative h-16 w-16 mb-2"> | ||||
| 					<Image | ||||
| 						src={`${BASE_URL}/${iconData.base}/${name}.${iconData.base}`} | ||||
| 						alt={`${name} icon`} | ||||
| 						fill | ||||
| 						className="object-contain p-1 group-hover:scale-110 transition-transform duration-300" | ||||
| 					/> | ||||
| 					{isLoading && ( | ||||
| 						<div className="absolute inset-0 bg-gray-200 dark:bg-gray-700 animate-pulse rounded" /> | ||||
| 					)} | ||||
| 					{/* Use <picture> tag for WebP support with fallback */} | ||||
| 					<picture> | ||||
| 						<source srcSet={webpSrc} type="image/webp" /> | ||||
| 						<source srcSet={originalSrc} type={`image/${iconData.base === 'svg' ? 'svg+xml' : iconData.base}`} /> | ||||
| 						{/* next/image as the img fallback and for optimization */} | ||||
| 						<Image | ||||
| 							src={originalSrc} // Fallback src for next/image | ||||
| 							alt={`${name} icon`} | ||||
| 							fill | ||||
| 							className={`object-contain p-1 group-hover:scale-110 transition-transform duration-300 ${isLoading ? 'opacity-0' : 'opacity-100 transition-opacity duration-500'}`} | ||||
| 							onLoadingComplete={() => setIsLoading(false)} | ||||
| 							// Add sizes prop for responsive optimization if needed, e.g., | ||||
| 							// sizes="(max-width: 640px) 50vw, (max-width: 1280px) 33vw, 16.6vw" | ||||
| 						/> | ||||
| 					</picture> | ||||
| 				</div> | ||||
| 				<span className="text-xs sm:text-sm text-center truncate w-full capitalize group- dark:group-hover:text-primary transition-colors duration-200 font-medium"> | ||||
| 					{name.replace(/-/g, " ")} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user