Finance
Loan-to-Value Card - Real Estate Finance
Monitor loan-to-value ratios and property valuations. Track mortgage metrics and lending risk.
Finance LTV Card
The Finance LTV Card displays Customer Lifetime Value metrics, helping businesses understand the long-term value of their customer relationships.
Preview
Installation
npx shadcn@latest add https://vectormotion.vercel.app/registry/finance-ltv-card.jsonFinance LTV Card
'use client'import React from 'react';import { Gem, ArrowUpRight } from 'lucide-react';import { ResponsiveContainer, LineChart, Line, Tooltip } 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 LTVData { month: string; ltv: number; cac: number; [key: string]: any;}interface LTVCardProps { isInteractive?: boolean; className?: string; title?: string; ltv?: string; ltvLabel?: string; ratioLabel?: string; ratioValue?: string; data?: LTVData[];}const DEFAULT_TITLE = "LTV";const DEFAULT_LTV = "$1,580";const DEFAULT_LTV_LABEL = "High Value";const DEFAULT_RATIO_LABEL = "LTV:CAC Ratio";const DEFAULT_RATIO_VALUE = "4.5x";const DEFAULT_DATA: LTVData[] = [ { month: 'Jan', ltv: 1200, cac: 300 }, { month: 'Feb', ltv: 1350, cac: 310 }, { month: 'Mar', ltv: 1420, cac: 305 }, { month: 'Apr', ltv: 1580, cac: 345 },];export const LTVCard: React.FC<LTVCardProps> = ({ isInteractive = true, className = "", title = DEFAULT_TITLE, ltv = DEFAULT_LTV, ltvLabel = DEFAULT_LTV_LABEL, ratioLabel = DEFAULT_RATIO_LABEL, ratioValue = DEFAULT_RATIO_VALUE, data = DEFAULT_DATA,}) => { const index = 29; 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">{ltv}</span> <span className="text-xs bg-emerald-500/10 text-emerald-600 px-1.5 py-0.5 rounded-full flex items-center gap-0.5"> <ArrowUpRight className="w-3 h-3" /> {ltvLabel} </span> </div> </div> <div className="rounded-lg bg-emerald-500/10 p-2 text-emerald-500"> <Gem 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%"> <LineChart data={data}> <Tooltip contentStyle={{ backgroundColor: 'var(--tooltip-bg)', borderRadius: '8px', border: 'none', color: 'var(--tooltip-text)' }} /> <Line name="LTV" type="monotone" dataKey="ltv" stroke="#10b981" // emerald-500 strokeWidth={3} dot={{ r: 3, fill: '#10b981' }} animationDuration={2000} /> <Line name="CAC" type="monotone" dataKey="cac" stroke="#ef4444" // rose-500 strokeWidth={2} strokeDasharray="5 5" dot={false} animationDuration={2000} /> </LineChart> </ResponsiveContainer> </div> </div> <div className="z-10 mt-2 flex items-center justify-between text-xs pt-2 border-t border-border"> <span className="text-muted-foreground">{ratioLabel}</span> <span className="font-bold text-foreground">{ratioValue}</span> </div> </motion.div> );};Props
Prop
Type