Vector Motion
Finance

EBITDA Card - Financial Performance

Monitor EBITDA and operating profitability metrics. Track earnings before interest, taxes, depreciation, and amortization.

Finance EBITDA Card

The Finance EBITDA Card displays EBITDA metrics, a key indicator of operational profitability and financial performance.

Preview

Installation

npx shadcn@latest add https://vectormotion.vercel.app/registry/finance-ebitda-card.json
Finance EBITDA Card
'use client'import React from 'react';import { Layers, CandlestickChart } from 'lucide-react';import { motion } from 'motion/react';import { clsx, type ClassValue } from "clsx"import { twMerge } from "tailwind-merge"import { ResponsiveContainer, BarChart, Bar, Cell, Tooltip } from 'recharts';function cn(...inputs: ClassValue[]) {   return twMerge(clsx(inputs))}interface TrendData {   month: string;   val: number;}interface EbitdaCardProps {   isInteractive?: boolean;   className?: string;   title?: string;   amount?: string;   periodLabel?: string;   trendData?: TrendData[];   revenue?: string;   cogs?: string;   opex?: string;   margin?: string;}const DEFAULT_TITLE = "EBITDA";const DEFAULT_AMOUNT = "$420.5k";const DEFAULT_PERIOD_LABEL = "Adj. TTM";const DEFAULT_TREND_DATA: TrendData[] = [   { month: 'Jan', val: 320 },   { month: 'Feb', val: 340 },   { month: 'Mar', val: 310 },   { month: 'Apr', val: 380 },   { month: 'May', val: 400 },   { month: 'Jun', val: 420 },];const DEFAULT_REVENUE = "$2.1M";const DEFAULT_COGS = "-$840k";const DEFAULT_OPEX = "-$735k";const DEFAULT_MARGIN = "20%";export const EbitdaCard: React.FC<EbitdaCardProps> = ({   isInteractive = true,   className = "",   title = DEFAULT_TITLE,   amount = DEFAULT_AMOUNT,   periodLabel = DEFAULT_PERIOD_LABEL,   trendData = DEFAULT_TREND_DATA,   revenue = DEFAULT_REVENUE,   cogs = DEFAULT_COGS,   opex = DEFAULT_OPEX,   margin = DEFAULT_MARGIN,}) => {   const index = 30;   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 text-muted-foreground">{periodLabel}</span>               </div>            </div>            <div className="rounded-lg bg-emerald-500/10 p-2 text-emerald-500">               <Layers className="h-5 w-5" />            </div>         </div>         <div className="relative z-10 flex-1 grid grid-cols-2 gap-4">            {/* Trend Chart side */}            <div className="flex flex-col justify-end">               <div className="h-[80px] w-full">                  <ResponsiveContainer width="100%" height="100%">                     <BarChart data={trendData}>                        <Tooltip cursor={{ fill: 'transparent' }} content={() => null} />                        <Bar dataKey="val" radius={[2, 2, 0, 0]}>                           {trendData.map((entry, index) => (                              <Cell key={`cell-${index}`} fill={index === 5 ? '#10b981' : '#e4e4e7'} className={index === 5 ? 'fill-emerald-500' : 'fill-zinc-200 dark:fill-zinc-800'} />                           ))}                        </Bar>                     </BarChart>                  </ResponsiveContainer>               </div>               <div className="text-center text-[10px] text-muted-foreground mt-1">6 Month Trend</div>            </div>            {/* Waterfall List side */}            <div className="flex flex-col justify-end gap-1.5 pb-1">               <div className="flex justify-between items-center text-xs">                  <span className="text-muted-foreground">Revenue</span>                  <span className="font-medium text-foreground">{revenue}</span>               </div>               <div className="flex justify-between items-center text-xs">                  <span className="text-muted-foreground">COGS</span>                  <span className="font-medium text-rose-500">{cogs}</span>               </div>               <div className="flex justify-between items-center text-xs">                  <span className="text-muted-foreground">Opex</span>                  <span className="font-medium text-rose-500">{opex}</span>               </div>               <div className="pt-1.5 mt-1 border-t border-border flex justify-between items-center text-xs">                  <span className="font-bold text-emerald-600">Margin</span>                  <span className="font-bold text-foreground">{margin}</span>               </div>            </div>         </div>      </motion.div>   );};

Props

Prop

Type