Vector Motion
E-Commerce

Top Products Card - Best Sellers

Identify and track top-selling products. Monitor bestsellers and product popularity trends.

Top Products Card

The Top Products Card Display best-selling products with sales and revenue rankings.

Preview

Installation

ash npx shadcn@latest add https://vectormotion.vercel.app/registry/top-products-card.json

Top Products Card
'use client';import React from "react";import { Trophy, Star } from "lucide-react";import { motion } from "motion/react";import { clsx, type ClassValue } from "clsx";import { twMerge } from "tailwind-merge";function cn(...inputs: ClassValue[]) {    return twMerge(clsx(inputs));}interface Product {    name: string;    sales: number;    revenue: number;    trend: string;    [key: string]: any;}interface TopProductsCardProps {    className?: string;    title?: string;    description?: string;    products?: Product[];}const DEFAULT_TITLE = "Top Products";const DEFAULT_DESCRIPTION = "Best Sellers";const DEFAULT_PRODUCTS: Product[] = [    { name: "Wireless Headphones", sales: 342, revenue: 25650, trend: "+15%" },    { name: "Smart Watch Pro", sales: 298, revenue: 44700, trend: "+22%" },    { name: "Laptop Stand", sales: 256, revenue: 12800, trend: "+8%" },];export const TopProductsCard: React.FC<TopProductsCardProps> = ({    className = "",    title = DEFAULT_TITLE,    description = DEFAULT_DESCRIPTION,    products = DEFAULT_PRODUCTS,}) => {    const isInteractive = true;    const index = 5;    return (        <motion.div            layoutId={isInteractive ? `card-${index}-${title}` : undefined}            transition={{ duration: 0.4, ease: "easeOut" }}            className={cn(                "relative overflow-hidden rounded-xl border border-border bg-card text-card-foreground p-6 shadow-sm transition-all flex flex-col group",                isInteractive                    ? "cursor-pointer hover:border-zinc-300 dark:hover:border-zinc-700"                    : "",                className,            )}        >            <div className="mb-4 flex items-start justify-between relative z-10">                <div>                    <h3 className="font-semibold text-lg tracking-tight text-foreground">                        {title}                    </h3>                    {description && (                        <p className="text-sm text-muted-foreground mt-1">{description}</p>                    )}                </div>                <div className="rounded-full bg-zinc-100 dark:bg-zinc-800 p-2 text-foreground flex items-center justify-center">                    <Trophy className="h-5 w-5 text-amber-500" />                </div>            </div>            <div className="relative z-10 flex-1 space-y-3">                {products.map((product, idx) => (                    <motion.div                        key={idx}                        initial={{ opacity: 0, x: -20 }}                        animate={{ opacity: 1, x: 0 }}                        transition={{ duration: 0.5, delay: idx * 0.1 }}                        className="bg-muted rounded-lg p-3"                    >                        <div className="flex items-start justify-between mb-2">                            <div className="flex items-center gap-2">                                <div                                    className={`w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold ${idx === 0                                            ? "bg-amber-500 text-white"                                            : idx === 1                                                ? "bg-zinc-300 dark:bg-zinc-600 text-foreground"                                                : "bg-orange-400 text-white"                                        }`}                                >                                    {idx + 1}                                </div>                                <span className="text-sm font-medium text-foreground">                                    {product.name}                                </span>                            </div>                            <span className="text-xs font-medium text-emerald-500">                                {product.trend}                            </span>                        </div>                        <div className="flex justify-between items-center text-xs">                            <span className="text-muted-foreground">                                {product.sales} units sold                            </span>                            <span className="font-bold text-foreground">                                ${product.revenue.toLocaleString()}                            </span>                        </div>                    </motion.div>                ))}            </div>        </motion.div>    );};

Usage

This component is a data-rich dashboard card displaying e-commerce metrics with animated visualizations and dark mode support. Perfect for dashboards, landing pages, and analytics interfaces.

Prop

Type