Vector Motion
E-Commerce

Mobile vs Desktop Card - Device Analytics

Analyze mobile versus desktop traffic and conversion rates. Monitor device-specific user behavior and performance.

Mobile vs Desktop Card

The Mobile vs Desktop Card Compare device analytics and user behavior.

Preview

Installation

ash npx shadcn@latest add https://vectormotion.vercel.app/registry/mobile-vs-desktop-card.json

Mobile vs Desktop Card
'use client';import React from "react";import { Smartphone, Monitor, 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 Device {  device: "Mobile" | "Desktop" | "Tablet";  sessions: number;  revenue: number;  conversion: number;  color: string;  [key: string]: any;}interface MobileVsDesktopCardProps {  className?: string;  title?: string;  description?: string;  devices?: Device[];}const DEFAULT_TITLE = "Mobile vs Desktop";const DEFAULT_DESCRIPTION = "Device Analytics";const DEFAULT_DEVICES: Device[] = [  {    device: "Mobile",    sessions: 15420,    revenue: 45200,    conversion: 2.8,    color: "bg-blue-500",  },  {    device: "Desktop",    sessions: 12350,    revenue: 62100,    conversion: 4.2,    color: "bg-purple-500",  },  {    device: "Tablet",    sessions: 3200,    revenue: 8900,    conversion: 2.1,    color: "bg-emerald-500",  },];export const MobileVsDesktopCard: React.FC<MobileVsDesktopCardProps> = ({  className = "",  title = DEFAULT_TITLE,  description = DEFAULT_DESCRIPTION,  devices = DEFAULT_DEVICES,}) => {  const isInteractive = true;  const index = 48;  const totalSessions = devices.reduce((sum, d) => sum + d.sessions, 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">          <Smartphone className="h-5 w-5 text-blue-500" />        </div>      </div>      <div className="relative z-10 flex-1">        <div className="text-2xl font-bold text-foreground mb-1">          {(totalSessions / 1000).toFixed(1)}K        </div>        <p className="text-sm text-muted-foreground mb-4">Total sessions</p>        <div className="space-y-3">          {devices.map((device, idx) => {            const percentage = Math.round(              (device.sessions / totalSessions) * 100,            );            return (              <motion.div                key={idx}                initial={{ opacity: 0, y: 5 }}                animate={{ opacity: 1, y: 0 }}                transition={{ duration: 0.4, delay: idx * 0.1 }}                className="bg-muted rounded-lg p-3"              >                <div className="flex justify-between items-center mb-2">                  <div className="flex items-center gap-2">                    {device.device === "Mobile" ? (                      <Smartphone className="h-4 w-4 text-blue-500" />                    ) : device.device === "Desktop" ? (                      <Monitor className="h-4 w-4 text-purple-500" />                    ) : (                      <Smartphone className="h-4 w-4 text-emerald-500" />                    )}                    <span className="text-sm font-medium text-foreground">                      {device.device}                    </span>                  </div>                  <span className="text-sm font-bold text-foreground">                    {percentage}%                  </span>                </div>                <div className="grid grid-cols-3 gap-2 text-xs">                  <div>                    <div className="text-muted-foreground">Sessions</div>                    <div className="font-medium text-foreground">                      {(device.sessions / 1000).toFixed(1)}K                    </div>                  </div>                  <div>                    <div className="text-muted-foreground">Revenue</div>                    <div className="font-medium text-emerald-500">                      ${(device.revenue / 1000).toFixed(0)}K                    </div>                  </div>                  <div>                    <div className="text-muted-foreground">CVR</div>                    <div className="font-medium text-foreground">                      {device.conversion}%                    </div>                  </div>                </div>              </motion.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