Finance
Payroll Summary Card - HR Finance
Monitor payroll summary and employee compensation. Track payroll expenses and labor costs.
Finance Payroll Summary Card
The Finance Payroll Summary Card displays payroll expenses and employee compensation data, helping HR and finance teams manage labor costs.
Preview
Installation
npx shadcn@latest add https://vectormotion.vercel.app/registry/finance-payroll-summary-card.jsonFinance Payroll Summary Card
'use client'import React from 'react';import { Users2, TrendingUp, DollarSign } from 'lucide-react';import { motion } from 'motion/react';import { clsx, type ClassValue } from "clsx"import { twMerge } from "tailwind-merge"import { ResponsiveContainer, BarChart, Bar, Tooltip, XAxis } from 'recharts';function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs))}interface PayrollData { name: string; eng: number; sales: number; ops: number; [key: string]: any;}interface BreakdownItem { dept: string; count: number; cost: string; growth: string;}interface PayrollSummaryCardProps { isInteractive?: boolean; className?: string; title?: string; totalCost?: string; employeeCount?: string; breakdown?: BreakdownItem[]; // data prob not used in render based on the viewed code, but included just in case data?: PayrollData[];}const DEFAULT_TITLE = "Payroll";const DEFAULT_TOTAL_COST = "$142k";const DEFAULT_EMPLOYEE_COUNT = "24 Emp.";const DEFAULT_DATA: PayrollData[] = [ { name: 'Payroll', eng: 45, sales: 30, ops: 25 },];const DEFAULT_BREAKDOWN: BreakdownItem[] = [ { dept: 'Engineering', count: 12, cost: '$85k', growth: '+1' }, { dept: 'Sales', count: 8, cost: '$42k', growth: '0' }, { dept: 'Operations', count: 4, cost: '$15k', growth: '+1' },];export const PayrollSummaryCard: React.FC<PayrollSummaryCardProps> = ({ isInteractive = true, className = "", title = DEFAULT_TITLE, totalCost = DEFAULT_TOTAL_COST, employeeCount = DEFAULT_EMPLOYEE_COUNT, breakdown = DEFAULT_BREAKDOWN,}) => { const index = 33; 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-5 shadow-sm transition-all flex flex-col h-full group", isInteractive ? "cursor-pointer hover:border-primary/50 hover:shadow-md" : "", className )} > <div className="mb-2 flex items-start justify-between relative z-10"> <div> <h3 className="font-semibold text-lg text-foreground"> {title} </h3> <div className="flex items-center gap-2 mt-1"> <span className="text-2xl font-bold text-foreground">{totalCost}</span> <span className="text-xs bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 rounded text-muted-foreground">{employeeCount}</span> </div> </div> <div className="rounded-lg bg-emerald-500/10 p-2 text-emerald-500"> <Users2 className="h-5 w-5" /> </div> </div> {/* Dense Breakdown List */} <div className="relative z-10 flex-1 space-y-2 mt-2"> {breakdown.map((dept, i) => ( <div key={dept.dept} className="flex items-center justify-between p-2 rounded bg-muted hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors"> <div className="flex flex-col"> <span className="text-xs font-semibold text-foreground">{dept.dept}</span> <span className="text-[10px] text-muted-foreground">{dept.count} Members</span> </div> <div className="text-right"> <div className="text-xs font-medium text-foreground">{dept.cost}</div> {dept.growth !== '0' && <span className="text-[10px] text-emerald-500">new hire</span>} </div> </div> ))} </div> <div className="absolute -bottom-4 -right-4 z-0 opacity-[0.03] pointer-events-none"> <Users2 className="w-24 h-24 text-foreground" /> </div> </motion.div> );};Props
Prop
Type