VectorMotion
E-Commerce

Product Categories Card - Category Performance

Monitor product category performance and sales distribution. Track top-performing categories and trends.

Product Categories Card

The Product Categories Card Monitor category performance and sales distribution.

Preview

Installation

ash npx shadcn@latest add https://www.vectormotion.dev/registry/product-categories-card.json

Product Categories Card
'use client';import React from "react";import { Grid, TrendingUp } 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 Category {  name: string;  revenue: number;  growth: number;  color: string;  [key: string]: any;}interface ProductCategoriesCardProps {  className?: string;  title?: string;  description?: string;  categories?: Category[];}const DEFAULT_TITLE = "Product Categories";const DEFAULT_DESCRIPTION = "Category Performance";const DEFAULT_CATEGORIES: Category[] = [  { name: "Electronics", revenue: 125000, growth: 15, color: "bg-blue-500" },  { name: "Apparel", revenue: 89000, growth: 8, color: "bg-purple-500" },  {    name: "Home & Garden",    revenue: 67000,    growth: 22,    color: "bg-emerald-500",  },  { name: "Sports", revenue: 45000, growth: -3, color: "bg-orange-500" },];export const ProductCategoriesCard: React.FC<ProductCategoriesCardProps> = ({  className = "",  title = DEFAULT_TITLE,  description = DEFAULT_DESCRIPTION,  categories = DEFAULT_CATEGORIES,}) => {  const isInteractive = true;  const index = 19;  const totalRevenue = categories.reduce((sum, cat) => sum + cat.revenue, 0);  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">          <Grid className="h-5 w-5 text-purple-500" />        </div>      </div>      <div className="relative z-10 flex-1">        <div className="text-2xl font-bold text-foreground mb-1">          ${(totalRevenue / 1000).toFixed(0)}K        </div>        <p className="text-sm text-muted-foreground mb-4">          Total category revenue        </p>        <div className="space-y-3">          {categories.map((category, idx) => {            const percentage = Math.round(              (category.revenue / totalRevenue) * 100,            );            return (              <div key={idx}>                <div className="flex justify-between items-center mb-1">                  <span className="text-sm text-foreground">                    {category.name}                  </span>                  <div className="flex items-center gap-2">                    <span                      className={`text-xs font-medium ${category.growth >= 0                          ? "text-emerald-500"                          : "text-red-500"                        }`}                    >                      {category.growth >= 0 ? "+" : ""}                      {category.growth}%                    </span>                    <span className="text-sm font-bold text-foreground">                      ${(category.revenue / 1000).toFixed(0)}K                    </span>                  </div>                </div>                <div className="flex items-center gap-2">                  <div className="flex-1 bg-zinc-100 dark:bg-zinc-800 rounded-full h-2 overflow-hidden">                    <motion.div                      initial={{ width: 0 }}                      animate={{ width: `${percentage}%` }}                      transition={{ duration: 1, delay: idx * 0.1 }}                      className={`h-full ${category.color} rounded-full`}                    />                  </div>                  <span className="text-xs text-muted-foreground w-8 text-right">                    {percentage}%                  </span>                </div>              </div>            );          })}        </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

On this page

Free block

Need this in production?

Unlock install commands, source access, commercial use, and AI prompts for all VectorMotion blocks.