Vector Motion
AI/ML

Experiment Tracker Card - ML Experiment Management

Track machine learning experiments with metrics, parameters, and results. Compare experiment runs and manage ML model development lifecycle.

Experiment Tracker Card

The Experiment Tracker Card displays machine learning experiment runs, parameters, and results, helping teams compare different model configurations.

Preview

Installation

npx shadcn@latest add https://vectormotion.vercel.app/registry/experiment-tracker-card.json
Experiment Tracker Card
'use client'import React from 'react';import { FlaskConical, Beaker } from 'lucide-react';import { motion } from 'motion/react';import { clsx, type ClassValue } from "clsx"import { twMerge } from "tailwind-merge"import { ResponsiveContainer, ScatterChart, Scatter, XAxis, YAxis, Tooltip, Cell, ZAxis } from 'recharts';function cn(...inputs: ClassValue[]) {   return twMerge(clsx(inputs))}interface ExperimentData {   id: number;   lift: number;   confidence: number;   name: string;   [key: string]: any;}interface ExperimentTrackerCardProps {   className?: string;   title?: string;   activeExperiments?: number;   annotation?: string;   data?: ExperimentData[];}const DEFAULT_DATA: ExperimentData[] = [   { id: 101, lift: 2, confidence: 90, name: 'Exp-101' },   { id: 102, lift: 5, confidence: 95, name: 'Exp-102' },   { id: 103, lift: -1, confidence: 60, name: 'Exp-103' },   { id: 104, lift: 3, confidence: 85, name: 'Exp-104' },   { id: 105, lift: 1, confidence: 70, name: 'Exp-105' },];const DEFAULT_TITLE = "Experiments";const DEFAULT_ACTIVE_EXPERIMENTS = 5;const DEFAULT_ANNOTATION = "Active A/B";export const ExperimentTrackerCard: React.FC<ExperimentTrackerCardProps> = ({   className = "",   title = DEFAULT_TITLE,   activeExperiments = DEFAULT_ACTIVE_EXPERIMENTS,   annotation = DEFAULT_ANNOTATION,   data = DEFAULT_DATA,}) => {   return (      <motion.div         initial={{ opacity: 0, y: 20 }}         animate={{ opacity: 1, y: 0 }}         transition={{ duration: 0.5, delay: 0.2 }}         className={cn(            "relative overflow-hidden rounded-2xl border border-border bg-card text-card-foreground shadow-sm transition-all hover:border-pink-300 dark:hover:border-pink-700 hover:shadow-md flex flex-col h-full",            className         )}      >         <div className="p-5 flex flex-col h-full relative z-10">            <div className="mb-4 flex items-start justify-between">               <div>                  <h3 className="font-bold text-lg text-foreground">                     {title}                  </h3>                  <div className="flex items-center gap-2 mt-1">                     <span className="text-2xl font-bold text-foreground">{activeExperiments}</span>                     <span className="text-xs font-medium text-pink-500 bg-pink-50 dark:bg-pink-900/20 px-1.5 py-0.5 rounded-full">                        {annotation}                     </span>                  </div>               </div>               <div className="rounded-lg border-2 border-pink-100 dark:border-pink-800 p-2 text-pink-500 dark:text-pink-400 flex items-center justify-center">                  <FlaskConical className="h-5 w-5" />               </div>            </div>            <div className="flex-1 w-full min-h-[140px] relative">               <ResponsiveContainer width="100%" height="100%">                  <ScatterChart margin={{ top: 10, right: 10, bottom: 0, left: -20 }}>                     <XAxis type="number" dataKey="lift" name="Lift" unit="%" tick={{ fontSize: 10 }} />                     <YAxis type="number" dataKey="confidence" name="Conf" unit="%" tick={{ fontSize: 10 }} />                     <ZAxis type="number" dataKey="id" range={[50, 200]} />                     <Tooltip                        cursor={{ strokeDasharray: '3 3' }}                        content={({ active, payload }) => {                           if (active && payload && payload.length) {                              return (                                 <div className="rounded-lg border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-800 p-2 shadow-sm text-xs">                                    <span className="font-bold text-pink-600 dark:text-pink-400">                                       {payload[0].payload.name}:                                    </span>                                    <div>Lift: {payload[0].payload.lift}%</div>                                    <div>Conf: {payload[0].payload.confidence}%</div>                                 </div>                              );                           }                           return null;                        }}                     />                     <Scatter data={data} fill="#ec4899">                        {data.map((entry, index) => (                           <Cell key={`cell-${index}`} fill={entry.lift > 0 ? '#10b981' : '#f43f5e'} />                        ))}                     </Scatter>                  </ScatterChart>               </ResponsiveContainer>               <div className="text-[10px] text-muted-foreground text-center">Impact (Lift) vs Certainty (Confidence)</div>            </div>            <div className="absolute -bottom-4 -right-4 z-0 opacity-5 pointer-events-none">               <Beaker className="w-40 h-40 text-pink-500" />            </div>         </div>      </motion.div>   );};

Props

Prop

Type

Usage

This component is a demo card displaying experiment tracking data with animated visualizations and dark mode support.