VectorMotion
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://www.vectormotion.dev/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

On this page

Free block

Need this in production?

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