Vector Motion
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.json
Finance 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.