Vector Motion
E-Commerce

Stock Levels Card - Real-time Inventory

Monitor real-time stock levels and inventory availability. Track inventory quantities by location.

Stock Levels Card

The Stock Levels Card Monitor real-time inventory levels across products.

Preview

Installation

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

Stock Levels Card
'use client';import React from "react";import { Package, AlertCircle, TrendingDown } 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;  stock: number;  status: "good" | "low" | "critical";  max: number;  [key: string]: any;}interface StockLevelsCardProps {  className?: string;  title?: string;  description?: string;  totalUnits?: string;  lowStockItems?: number;  products?: Product[];}const DEFAULT_TITLE = "Stock Levels";const DEFAULT_DESCRIPTION = "Real-time inventory tracking";const DEFAULT_TOTAL_UNITS = "824 units";const DEFAULT_LOW_STOCK_ITEMS = 2;const DEFAULT_PRODUCTS: Product[] = [  { name: "Wireless Earbuds", stock: 245, status: "good", max: 500 },  { name: "Smart Watch", stock: 89, status: "low", max: 200 },  { name: "Phone Case", stock: 456, status: "good", max: 600 },  { name: "USB-C Cable", stock: 34, status: "critical", max: 150 },];export const StockLevelsCard: React.FC<StockLevelsCardProps> = ({  className = "",  title = DEFAULT_TITLE,  description = DEFAULT_DESCRIPTION,  totalUnits = DEFAULT_TOTAL_UNITS,  lowStockItems = DEFAULT_LOW_STOCK_ITEMS,  products = DEFAULT_PRODUCTS,}) => {  const isInteractive = true;  const index = 11;  const getStatusColor = (status: string) => {    if (status === "good") return "bg-emerald-500";    if (status === "low") return "bg-amber-500";    return "bg-red-500";  };  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">          <Package className="h-5 w-5 text-blue-500" />        </div>      </div>      <div className="relative z-10 flex-1">        <div className="flex items-center gap-2 mb-4">          <div className="text-2xl font-bold text-foreground">{totalUnits}</div>          <div className="flex items-center gap-1 text-sm">            <TrendingDown className="h-4 w-4 text-amber-500" />            <span className="text-amber-500">{lowStockItems} low stock</span>          </div>        </div>        <div className="space-y-3">          {products.map((product, idx) => (            <div key={idx}>              <div className="flex justify-between items-center mb-1">                <div className="flex items-center gap-2">                  <span className="text-sm text-foreground">                    {product.name}                  </span>                  {product.status === "critical" && (                    <AlertCircle className="h-3 w-3 text-red-500" />                  )}                </div>                <span className="text-sm font-bold text-foreground">                  {product.stock}                </span>              </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: `${(product.stock / product.max) * 100}%`,                    }}                    transition={{ duration: 1, delay: idx * 0.1 }}                    className={`h-full ${getStatusColor(product.status)} rounded-full`}                  />                </div>                <span className="text-xs text-muted-foreground w-12 text-right">                  {Math.round((product.stock / product.max) * 100)}%                </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