Vector Motion
Finance

Interest Coverage Card - Debt Service

Monitor interest coverage ratios and debt obligations. Track ability to service debt payments.

Finance Interest Coverage Card

The Finance Interest Coverage Card displays the interest coverage ratio, measuring a company's ability to pay interest on outstanding debt.

Preview

Installation

npx shadcn@latest add https://vectormotion.vercel.app/registry/finance-interest-coverage-card.json
Finance Interest Coverage Card
'use client'import React from 'react';import { ShieldAlert } from 'lucide-react';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 InterestCoverageCardProps {  isInteractive?: boolean;  className?: string;  title?: string;  description?: string;  value?: number;  max?: number;  statusText?: string;  statusSubtext?: string;}const DEFAULT_TITLE = "Solvency";const DEFAULT_DESCRIPTION = "Interest Coverage";const DEFAULT_VALUE = 4.2;const DEFAULT_MAX = 6.0;const DEFAULT_STATUS_TEXT = "Healthy (> 3.0x)";const DEFAULT_STATUS_SUBTEXT = "EBIT / Interest Exp";export const InterestCoverageCard: React.FC<InterestCoverageCardProps> = ({  isInteractive = true,  className = "",  title = DEFAULT_TITLE,  description = DEFAULT_DESCRIPTION,  value = DEFAULT_VALUE,  max = DEFAULT_MAX,  statusText = DEFAULT_STATUS_TEXT,  statusSubtext = DEFAULT_STATUS_SUBTEXT,}) => {  // Gauge Config  const cx = 50;  const cy = 50;  const r = 40;  const circumference = Math.PI * r;  const progress = Math.min(value / max, 1);  const offset = circumference - (progress * circumference);  const index = 40;  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-6 shadow-sm transition-all flex flex-col group",        isInteractive ? "cursor-pointer hover:border-zinc-300 dark:hover:border-zinc-700" : "",        className      )}    >      <div className="mb-4 flex items-start justify-between relative z-10">        <div>          <h3 className="font-semibold text-lg tracking-tight text-foreground">            {title}          </h3>          {description && (            <p className="text-sm text-muted-foreground mt-1">              {description}            </p>          )}        </div>        <div className="rounded-full bg-zinc-100 dark:bg-zinc-800 p-2 text-foreground flex items-center justify-center">          <ShieldAlert className="h-5 w-5" />        </div>      </div>      <div className="relative z-10 flex-1">        <div className="flex flex-col items-center py-2">          <div className="relative w-40 h-20 overflow-hidden flex justify-center mb-2">            <svg viewBox="0 0 100 50" className="w-full h-full">              {/* Track */}              <path                d="M 10 50 A 40 40 0 0 1 90 50"                fill="none"                stroke="currentColor"                strokeWidth="10"                className="text-zinc-200 dark:text-zinc-800"                strokeLinecap="round"              />              {/* Fill */}              <motion.path                d="M 10 50 A 40 40 0 0 1 90 50"                fill="none"                stroke="#10b981"                strokeWidth="10"                strokeLinecap="round"                strokeDasharray={circumference}                initial={{ strokeDashoffset: circumference }}                animate={{ strokeDashoffset: offset }}                transition={{ duration: 1.5, ease: "easeOut" }}              />            </svg>            <div className="absolute bottom-0">              <span className="text-xl font-bold text-foreground">{value}x</span>            </div>          </div>          <div className="text-center">            <p className="text-xs text-muted-foreground">{statusText}</p>            <p className="text-[10px] text-muted-foreground mt-1">{statusSubtext}</p>          </div>        </div>      </div>    </motion.div>  );};

Props

Prop

Type