Vector Motion
Finance

Commodities Card - Commodity Trading

Monitor commodity prices and trading positions. Track hedging strategies and market exposure.

Finance Commodities Card

The Finance Commodities Card displays current commodity prices and market trends, helping traders and investors monitor commodity markets.

Preview

Installation

npx shadcn@latest add https://vectormotion.vercel.app/registry/finance-commodities-card.json
Finance Commodities Card
'use client';'use client';import React from 'react';import { Droplet, TrendingUp, TrendingDown } from 'lucide-react';import { motion } from 'motion/react';import { clsx, type ClassValue } from "clsx"import { twMerge } from "tailwind-merge"import { ResponsiveContainer, AreaChart, Area } from 'recharts';function cn(...inputs: ClassValue[]) {  return twMerge(clsx(inputs))}interface CommodityItem {  name: string;  price: string;  change: string;  data: number[];}interface CommoditiesCardProps {  isInteractive?: boolean;  className?: string;  title?: string;  subtitle?: string;  items?: CommodityItem[];}const DEFAULT_TITLE = "Commodities";const DEFAULT_SUBTITLE = "Live Markets";const DEFAULT_ITEMS: CommodityItem[] = [  { name: 'Brent Crude', price: '$85.40', change: '+1.2%', data: [82, 83, 84, 85, 84, 85, 85.4] },  { name: 'Gold Spot', price: '$1,940', change: '-0.4%', data: [1950, 1948, 1945, 1942, 1940, 1938, 1940] },  { name: 'Natural Gas', price: '$2.95', change: '+2.1%', data: [2.8, 2.85, 2.9, 2.88, 2.92, 2.94, 2.95] },];export const CommoditiesCard: React.FC<CommoditiesCardProps> = ({  isInteractive = true,  className = "",  title = DEFAULT_TITLE,  subtitle = DEFAULT_SUBTITLE,  items = DEFAULT_ITEMS,}) => {  const index = 47;  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-xs text-muted-foreground">{subtitle}</span>          </div>        </div>        <div className="rounded-lg bg-emerald-500/10 p-2 text-emerald-500">          <Droplet className="h-5 w-5" />        </div>      </div>      <div className="relative z-10 flex-1">        <div className="space-y-4 mt-2">          {items.map(item => {            const isPositive = item.change.startsWith('+');            return (              <div key={item.name} className="flex items-center justify-between">                <div>                  <div className="text-xs font-medium text-muted-foreground">{item.name}</div>                  <div className="text-sm font-bold text-foreground">{item.price}</div>                </div>                <div className="h-8 w-16">                  <ResponsiveContainer width="100%" height="100%">                    <AreaChart data={item.data.map((v, i) => ({ value: v }))}>                      <defs>                        <linearGradient id={`grad-${item.name}`} x1="0" y1="0" x2="0" y2="1">                          <stop offset="5%" stopColor={isPositive ? "#10b981" : "#f43f5e"} stopOpacity={0.3} />                          <stop offset="95%" stopColor={isPositive ? "#10b981" : "#f43f5e"} stopOpacity={0} />                        </linearGradient>                      </defs>                      <Area                        type="monotone"                        dataKey="value"                        stroke={isPositive ? "#10b981" : "#f43f5e"}                        fill={`url(#grad-${item.name})`}                        strokeWidth={2}                      />                    </AreaChart>                  </ResponsiveContainer>                </div>                <div className={`text-xs font-medium flex items-center gap-0.5 ${isPositive ? 'text-emerald-600' : 'text-rose-500'}`}>                  {isPositive ? <TrendingUp className="w-3 h-3" /> : <TrendingDown className="w-3 h-3" />}                  {item.change}                </div>              </div>            )          })}        </div>      </div>    </motion.div>  );};

Props

Prop

Type