VectorMotion
E-Commerce

Sales Funnel Card - Conversion Tracking

Visualize complete sales funnel from awareness to conversion. Track funnel drop-off and optimize each stage.

Sales Funnel Card

The Sales Funnel Card Visualize conversion funnel from visitors to purchases.

Preview

Installation

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

Sales Funnel Card
'use client';import React from "react";import { Filter, Users } 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 FunnelStage {  stage: string;  count: number;  percentage: number;  color: string;  [key: string]: any;}interface SalesFunnelCardProps {  className?: string;  title?: string;  description?: string;  overallConversion?: string;  funnelStages?: FunnelStage[];}const DEFAULT_TITLE = "Sales Funnel";const DEFAULT_DESCRIPTION = "Conversion Flow";const DEFAULT_OVERALL_CONVERSION = "6.0%";const DEFAULT_FUNNEL_STAGES: FunnelStage[] = [  { stage: "Visitors", count: 10000, percentage: 100, color: "bg-blue-500" },  {    stage: "Product Views",    count: 5000,    percentage: 50,    color: "bg-purple-500",  },  {    stage: "Add to Cart",    count: 2000,    percentage: 20,    color: "bg-indigo-500",  },  { stage: "Checkout", count: 800, percentage: 8, color: "bg-violet-500" },  { stage: "Purchase", count: 600, percentage: 6, color: "bg-emerald-500" },];export const SalesFunnelCard: React.FC<SalesFunnelCardProps> = ({  className = "",  title = DEFAULT_TITLE,  description = DEFAULT_DESCRIPTION,  overallConversion = DEFAULT_OVERALL_CONVERSION,  funnelStages = DEFAULT_FUNNEL_STAGES,}) => {  const isInteractive = true;  const index = 4;  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">          <Filter className="h-5 w-5 text-indigo-500" />        </div>      </div>      <div className="relative z-10 flex-1">        <div className="space-y-2">          {funnelStages.map((stage, idx) => (            <div key={idx}>              <div className="flex justify-between items-center mb-1">                <span className="text-sm font-medium text-foreground">                  {stage.stage}                </span>                <div className="flex items-center gap-2">                  <span className="text-sm font-bold text-foreground">                    {stage.count.toLocaleString()}                  </span>                  <span className="text-xs text-muted-foreground">                    ({stage.percentage}%)                  </span>                </div>              </div>              <motion.div                initial={{ width: 0 }}                animate={{ width: `${stage.percentage}%` }}                transition={{ duration: 0.8, delay: idx * 0.1 }}                className={`h-8 ${stage.color} rounded-lg flex items-center justify-center`}                style={{ minWidth: "60px" }}              >                {idx < funnelStages.length - 1 && (                  <span className="text-xs text-white font-medium">                    {(                      (funnelStages[idx + 1].count / stage.count) *                      100                    ).toFixed(1)}                    % →                  </span>                )}              </motion.div>            </div>          ))}        </div>        <div className="mt-4 pt-4 border-t border-border">          <div className="flex justify-between items-center">            <span className="text-sm text-muted-foreground">              Overall Conversion            </span>            <span className="text-lg font-bold text-emerald-500">              {overallConversion}            </span>          </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.