Finance
Monthly Recurring Revenue Card - Subscription Metrics
Monitor monthly recurring revenue and subscription growth. Track MRR trends and revenue stability.
Finance MRR Card
The Finance MRR Card presents Monthly Recurring Revenue growth trends with a bar chart visualization, helping SaaS and subscription businesses monitor their recurring revenue performance over time.
Preview
Installation
npx shadcn@latest add https://vectormotion.vercel.app/registry/finance-mrr-card.jsonFinance MRR Card
'use client'import React from 'react';import { BarChart3, TrendingUp } from 'lucide-react';import { ResponsiveContainer, AreaChart, Area, Tooltip, XAxis } from 'recharts';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 MRRData { month: string; val: number; [key: string]: any;}interface MRRCardProps { isInteractive?: boolean; className?: string; title?: string; amount?: string; growth?: string; data?: MRRData[];}const DEFAULT_TITLE = "MRR Growth";const DEFAULT_AMOUNT = "$71.2k";const DEFAULT_GROWTH = "+12.8%";const DEFAULT_DATA: MRRData[] = [ { month: 'Jun', val: 45 }, { month: 'Jul', val: 48 }, { month: 'Aug', val: 52 }, { month: 'Sep', val: 58 }, { month: 'Oct', val: 63 }, { month: 'Nov', val: 71 },];export const MRRCard: React.FC<MRRCardProps> = ({ isInteractive = true, className = "", title = DEFAULT_TITLE, amount = DEFAULT_AMOUNT, growth = DEFAULT_GROWTH, data = DEFAULT_DATA,}) => { const index = 26; 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">{amount}</span> <span className="text-xs font-medium text-emerald-600 bg-emerald-500/10 px-1.5 py-0.5 rounded-full flex items-center gap-0.5"> <TrendingUp className="w-3 h-3" /> {growth} </span> </div> </div> <div className="rounded-lg bg-emerald-500/10 p-2 text-emerald-500"> <BarChart3 className="h-5 w-5" /> </div> </div> <div className="relative z-10 flex-1 min-h-[140px]"> <div className="absolute inset-0"> <ResponsiveContainer width="100%" height="100%"> <AreaChart data={data}> <defs> <linearGradient id="colorMRR" x1="0" y1="0" x2="0" y2="1"> <stop offset="5%" stopColor="#10b981" stopOpacity={0.3} /> <stop offset="95%" stopColor="#10b981" stopOpacity={0} /> </linearGradient> </defs> <Tooltip cursor={{ stroke: '#10b981', strokeWidth: 1, strokeDasharray: '3 3' }} contentStyle={{ backgroundColor: 'var(--tooltip-bg)', borderRadius: '8px', border: 'none', color: 'var(--tooltip-text)' }} formatter={(val) => [`$${val}k`, 'MRR']} /> <XAxis dataKey="month" axisLine={false} tickLine={false} tick={{ fontSize: 10, fill: '#71717a' }} /> <Area type="monotone" dataKey="val" stroke="#10b981" fill="url(#colorMRR)" strokeWidth={2} animationDuration={1500} /> </AreaChart> </ResponsiveContainer> </div> </div> </motion.div> );};Props
Prop
Type