Vector Motion
E-Commerce

Session Duration Card - User Engagement

Monitor average session duration and user engagement time. Track visitor attention and content effectiveness.

Session Duration Card

The Session Duration Card Monitor user engagement time and session length.

Preview

Installation

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

Session Duration Card
'use client';import React from "react";import { Clock, 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 Segment {  segment: string;  duration: string;  seconds: number;  engagement: "low" | "medium" | "high";  [key: string]: any;}interface SessionDurationCardProps {  className?: string;  title?: string;  description?: string;  averageSessionTime?: string;  sessionTimeChange?: number;  segments?: Segment[];}const DEFAULT_TITLE = "Session Duration";const DEFAULT_DESCRIPTION = "Engagement Time";const DEFAULT_AVERAGE_SESSION_TIME = "4:51";const DEFAULT_SESSION_TIME_CHANGE = 18;const DEFAULT_SEGMENTS: Segment[] = [  {    segment: "New Visitors",    duration: "2:15",    seconds: 135,    engagement: "low",  },  {    segment: "Returning",    duration: "4:32",    seconds: 272,    engagement: "medium",  },  {    segment: "Loyal Customers",    duration: "7:48",    seconds: 468,    engagement: "high",  },];export const SessionDurationCard: React.FC<SessionDurationCardProps> = ({  className = "",  title = DEFAULT_TITLE,  description = DEFAULT_DESCRIPTION,  averageSessionTime = DEFAULT_AVERAGE_SESSION_TIME,  sessionTimeChange = DEFAULT_SESSION_TIME_CHANGE,  segments = DEFAULT_SEGMENTS,}) => {  const isInteractive = true;  const index = 44;  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">          <Clock className="h-5 w-5 text-purple-500" />        </div>      </div>      <div className="relative z-10 flex-1">        <div className="flex items-baseline gap-2 mb-2">          <div className="text-3xl font-bold text-foreground">            {averageSessionTime}          </div>          <div className="flex items-center gap-1 text-sm">            <TrendingUp className="h-4 w-4 text-emerald-500" />            <span className="text-emerald-500">+{sessionTimeChange}%</span>          </div>        </div>        <p className="text-sm text-muted-foreground mb-4">          Average session time        </p>        <div className="space-y-3">          {segments.map((seg, idx) => (            <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">                <span className="text-sm font-medium text-foreground">                  {seg.segment}                </span>                <span className="text-lg font-bold text-purple-500">                  {seg.duration}                </span>              </div>              <div className="flex justify-between text-xs">                <span className="text-muted-foreground">Engagement</span>                <span                  className={`font-medium ${seg.engagement === "high"                      ? "text-emerald-500"                      : seg.engagement === "medium"                        ? "text-blue-500"                        : "text-amber-500"                    }`}                >                  {seg.engagement.toUpperCase()}                </span>              </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