Finance
Net Income Card - Bottom Line
Monitor net income and profitability. Track earnings after all expenses and taxes.
Finance Net Income Card
The Finance Net Income Card displays net income metrics and trends, showing the company's bottom-line profitability after all expenses.
Preview
Installation
npx shadcn@latest add https://vectormotion.vercel.app/registry/finance-net-income-card.jsonFinance Net Income Card
'use client'import React from 'react';import { TrendingDown, TrendingUp, DollarSign, Wallet } from 'lucide-react';import { ResponsiveContainer, ComposedChart, Bar, Line, XAxis, Tooltip, Cell, ReferenceLine } 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 NetIncomeData { month: string; value: number; margin: number; [key: string]: any;}interface NetIncomeCardProps { isInteractive?: boolean; className?: string; title?: string; totalIncome?: string; incomeLabel?: string; profitLabel?: string; targetLabel?: string; data?: NetIncomeData[];}const DEFAULT_TITLE = "Net Income";const DEFAULT_TOTAL_INCOME = "$41.7k";const DEFAULT_INCOME_LABEL = "YTD";const DEFAULT_PROFIT_LABEL = "+12.4% Profit";const DEFAULT_TARGET_LABEL = "Target: $40k";const DEFAULT_DATA: NetIncomeData[] = [ { month: 'Q1', value: 12500, margin: 12 }, { month: 'Q2', value: 15000, margin: 15 }, { month: 'Q3', value: -4000, margin: -5 }, // Loss { month: 'Q4', value: 18200, margin: 18 },];export const NetIncomeCard: React.FC<NetIncomeCardProps> = ({ isInteractive = true, className = "", title = DEFAULT_TITLE, totalIncome = DEFAULT_TOTAL_INCOME, incomeLabel = DEFAULT_INCOME_LABEL, profitLabel = DEFAULT_PROFIT_LABEL, targetLabel = DEFAULT_TARGET_LABEL, data = DEFAULT_DATA,}) => { const index = 17; 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">{totalIncome}</span> <span className="text-xs text-muted-foreground">{incomeLabel}</span> </div> </div> <div className="rounded-lg bg-emerald-500/10 p-2 text-emerald-500"> <Wallet 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%"> <ComposedChart data={data}> <XAxis dataKey="month" axisLine={false} tickLine={false} tick={{ fill: '#71717a', fontSize: 10 }} dy={10} /> <Tooltip cursor={{ fill: 'transparent' }} content={({ active, payload }) => { if (active && payload && payload.length) { return ( <div className="rounded-lg border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-800 p-2 shadow-sm text-xs"> <div className="font-bold text-foreground">${payload[0].value}</div> <div className="text-muted-foreground">Margin: {payload[0].payload.margin}%</div> </div> ); } return null; }} /> <ReferenceLine y={0} stroke="#e4e4e7" strokeDasharray="3 3" /> <Bar dataKey="value" radius={[4, 4, 4, 4]} barSize={24} > {data.map((entry, index) => ( <Cell key={`cell-${index}`} fill={entry.value >= 0 ? '#18181b' : '#ef4444'} className={entry.value >= 0 ? 'fill-zinc-900 dark:fill-zinc-100' : 'fill-rose-500'} /> ))} </Bar> <Line type="monotone" dataKey="margin" stroke="#10b981" strokeWidth={2} dot={false} opacity={0.5} /> </ComposedChart> </ResponsiveContainer> </div> </div> <div className="z-10 mt-2 flex items-center justify-between text-xs pt-2 border-t border-border"> <div className="flex items-center gap-1.5 bg-emerald-500/10 text-emerald-500 px-2 py-1 rounded"> <TrendingUp className="w-3 h-3" /> <span>{profitLabel}</span> </div> <span className="text-muted-foreground">{targetLabel}</span> </div> </motion.div> );};Props
Prop
Type