Finance
Stock Watchlist Card - Stock Tracking
Monitor stock watchlist and price tracking. Track stock performance and investment targets.
Finance Stock Watchlist Card
The Finance Stock Watchlist Card displays a customizable list of stocks to monitor, showing current prices and performance metrics.
Preview
Installation
npx shadcn@latest add https://vectormotion.vercel.app/registry/finance-stock-watchlist-card.jsonFinance Stock Watchlist Card
'use client'import React from 'react';import { LineChart as LineChartIcon, ArrowRight } from 'lucide-react';import { ResponsiveContainer, LineChart, Line, YAxis } 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 StockData { symbol: string; price: string; change: string; data: number[]; [key: string]: any;}interface StockWatchlistCardProps { isInteractive?: boolean; className?: string; title?: string; subtitle?: string; watchlist?: StockData[];}const DEFAULT_TITLE = "Market Watch";const DEFAULT_SUBTITLE = "Intraday";const DEFAULT_WATCHLIST: StockData[] = [ { symbol: 'NVDA', price: '425.12', change: '+3.2%', data: [410, 415, 412, 418, 420, 422, 425] }, { symbol: 'MSFT', price: '330.55', change: '+1.1%', data: [325, 326, 328, 327, 329, 330, 330] }, { symbol: 'AMZN', price: '128.30', change: '-0.5%', data: [130, 131, 129, 128, 127, 128, 128] },];export const StockWatchlistCard: React.FC<StockWatchlistCardProps> = ({ isInteractive = true, className = "", title = DEFAULT_TITLE, subtitle = DEFAULT_SUBTITLE, watchlist = DEFAULT_WATCHLIST,}) => { const index = 46; 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"> <LineChartIcon className="h-5 w-5" /> </div> </div> <div className="relative z-10 flex-1"> <div className="space-y-3 mt-1"> {watchlist.map((stock, i) => ( <motion.div key={stock.symbol} initial={{ opacity: 0, x: -10 }} animate={{ opacity: 1, x: 0 }} transition={{ delay: i * 0.1 }} className="flex items-center justify-between py-1 border-b border-transparent hover:border-zinc-100 dark:hover:border-zinc-800/50 hover:bg-zinc-50 dark:hover:bg-zinc-800/20 -mx-2 px-2 rounded-lg transition-all" > <div className="w-16"> <div className="font-bold text-sm text-foreground">{stock.symbol}</div> <div className={`text-[10px] ${stock.change.startsWith('+') ? 'text-emerald-600' : 'text-rose-500'}`}> {stock.change} </div> </div> {/* Sparkline */} <div className="h-8 w-20"> <ResponsiveContainer width="100%" height="100%"> <LineChart data={stock.data.map(v => ({ val: v }))}> <YAxis domain={['dataMin', 'dataMax']} hide /> <Line type="monotone" dataKey="val" stroke={stock.change.startsWith('+') ? '#10b981' : '#f43f5e'} strokeWidth={2} dot={false} isAnimationActive={true} animationDuration={1000} /> </LineChart> </ResponsiveContainer> </div> <div className="text-right w-16"> <div className="font-medium text-sm text-foreground">${stock.price}</div> </div> </motion.div> ))} </div> </div> <div className="z-10 mt-2 flex items-center justify-center pt-2 text-xs"> <button className="flex items-center gap-1 font-medium text-emerald-500 hover:underline"> Full Watchlist <ArrowRight className="w-3 h-3" /> </button> </div> </motion.div> );};Props
Prop
Type
Usage
This component is a demo card displaying stock watchlist data with animated visualizations and dark mode support.