Vector Motion
Finance

Vendor Payments Card - Accounts Payable

Monitor vendor payments and supplier invoices. Track payables and payment timing.

Finance Vendor Payments Card

The Finance Vendor Payments Card displays upcoming vendor payments and payment history, helping businesses manage their payables efficiently.

Preview

Installation

npx shadcn@latest add https://vectormotion.vercel.app/registry/finance-vendor-payments-card.json
Finance Vendor Payments Card
'use client'import React from 'react';import { Truck, Check } from 'lucide-react';import { motion } from 'motion/react';import { clsx, type ClassValue } from "clsx"import { twMerge } from "tailwind-merge"import { ResponsiveContainer, RadialBarChart, RadialBar, PolarAngleAxis } from 'recharts';function cn(...inputs: ClassValue[]) {   return twMerge(clsx(inputs))}interface Vendor {   name: string;   amount: string;   status: string;}interface PaymentData {   name: string;   value: number;   fill: string;   [key: string]: any;}interface VendorPaymentsCardProps {   isInteractive?: boolean;   className?: string;   title?: string;   percentage?: string;   statusLabel?: string;   vendors?: Vendor[];   data?: PaymentData[];   healthLabel?: string;   healthStatus?: string;}const DEFAULT_TITLE = "Vendor Payments";const DEFAULT_PERCENTAGE = "92%";const DEFAULT_STATUS_LABEL = "On-Time";const DEFAULT_VENDORS: Vendor[] = [   { name: 'AWS Cloud', amount: '$12.4k', status: 'Paid' },   { name: 'WeWork', amount: '$8.2k', status: 'Paid' },];const DEFAULT_DATA: PaymentData[] = [{ name: 'OnTime', value: 92, fill: '#10b981' }]; // Emeraldconst DEFAULT_HEALTH_LABEL = "Health";const DEFAULT_HEALTH_STATUS = "Good";export const VendorPaymentsCard: React.FC<VendorPaymentsCardProps> = ({   isInteractive = true,   className = "",   title = DEFAULT_TITLE,   percentage = DEFAULT_PERCENTAGE,   statusLabel = DEFAULT_STATUS_LABEL,   vendors = DEFAULT_VENDORS,   data = DEFAULT_DATA,   healthLabel = DEFAULT_HEALTH_LABEL,   healthStatus = DEFAULT_HEALTH_STATUS,}) => {   const index = 25;   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">{percentage}</span>                  <span className="text-xs text-muted-foreground">{statusLabel}</span>               </div>            </div>            <div className="rounded-lg bg-emerald-500/10 p-2 text-emerald-500">               <Truck className="h-5 w-5" />            </div>         </div>         <div className="relative z-10 flex-1 min-h-[140px] flex items-center justify-center">            <div className="h-[160px] w-full relative">               <ResponsiveContainer width="100%" height="100%">                  <RadialBarChart                     cx="50%"                     cy="60%"                     innerRadius="60%"                     outerRadius="100%"                     barSize={16}                     data={data}                     startAngle={180}                     endAngle={0}                  >                     <PolarAngleAxis                        type="number"                        domain={[0, 100]}                        angleAxisId={0}                        tick={false}                     />                     <RadialBar                        background={{ fill: '#f4f4f5' }} // zinc-100                        dataKey="value"                        cornerRadius={10}                     />                  </RadialBarChart>               </ResponsiveContainer>               <div className="absolute inset-0 top-10 flex flex-col items-center justify-center pointer-events-none pb-4">                  <span className="text-xs text-muted-foreground uppercase tracking-widest">{healthLabel}</span>                  <span className="font-bold text-foreground text-lg">{healthStatus}</span>               </div>            </div>         </div>         <div className="space-y-2 border-t border-border pt-2 relative z-10">            {vendors.map((v) => (               <div key={v.name} className="flex items-center justify-between text-xs">                  <span className="text-zinc-600 dark:text-muted-foreground">{v.name}</span>                  <div className="flex items-center gap-2">                     <span className="font-medium text-foreground">{v.amount}</span>                     <Check className="h-3 w-3 text-emerald-500" />                  </div>               </div>            ))}         </div>      </motion.div>   );};

Props

Prop

Type

Usage

This component is a demo card displaying vendor payment information with animated visualizations and dark mode support.