LAKSHAY SINGLA

Interactive AI Model Comparison Dashboard

AI chats

About

A sophisticated, interactive dashboard for comparing AI models:

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Interactive AI Model Comparison Dashboard to your project and fits it to your theme.

Code

How Interactive AI Model Comparison Dashboard is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

import { useState } from "react";
import { cn } from "@/lib/utils";
import { CheckCircle, AlertCircle, Zap, Activity, BarChart3 } from "lucide-react";

export const Component = () => {
  const [activeTab, setActiveTab] = useState("performance");
  const [selectedModel, setSelectedModel] = useState("gpt-4");

  const models = [
    { id: "gpt-4", name: "GPT-4", color: "#10B981" },
    { id: "claude-3", name: "Claude 3", color: "#8B5CF6" },
    { id: "llama-3", name: "Llama 3", color: "#EC4899" },
    { id: "mistral", name: "Mistral", color: "#3B82F6" }
  ];

  const performanceData = {
    "gpt-4": [89, 92, 91, 96],
    "claude-3": [82, 88, 94, 97],
    "llama-3": [76, 81, 87, 91],
    "mistral": [79, 84, 89, 92]
  };

  const quarters = ["Q1", "Q2", "Q3", "Q4"];

  const accuracyData = {
    categories: ["Translation", "Coding", "Creative", "Reasoning"],
    "gpt-4": [95, 92, 88, 94],
    "claude-3": [93, 89, 91, 96],
    "llama-3": [88, 84, 82, 87],
    "mistral": [90, 85, 79, 88]
  };

  const modelDetails = {
    "gpt-4": {
      strengths: ["Complex reasoning", "Code generation", "Multilingual"],
      limitations: ["Training cutoff", "Hallucinations", "Context length"],
      speed: 92,
      accuracy: 94
    },
    "claude-3": {
      strengths: ["Long context", "Creative writing", "Safety guardrails"],
      limitations: ["Technical reasoning", "Coding", "Math problems"],
      speed: 88,
      accuracy: 95
    },
    "llama-3": {
      strengths: ["Open source", "Local deployment", "Customizable"],
      limitations: ["Less refined", "Resource intensive", "Smaller knowledge base"],
      speed: 86,
      accuracy: 88
    },
    "mistral": {
      strengths: ["Efficiency", "Low resource usage", "Specialization options"],
      limitations: ["Less general knowledge", "Narrower capabilities", "Less training data"],
      speed: 90,
      accuracy: 86
    }
  };

  // Custom chart components
  const CustomBarChart = ({ data, labels, max = 100, height = 250 }) => {
    const barWidth = `${100 / data.length - 2}%`;
    
    return (
      <div className="w-full" style={{ height: `${height}px` }}>

        <div className="flex h-full">
          {data.map((value, index) => (
            <div key={index} className="flex flex-col items-center justify-end flex-1 gap-2">
              <div className="w-full flex justify-center items-end h-[85%]">
                <div 
                  className="rounded-t-md transition-all duration-300 ease-out"
                  style={{ 
                    height: `${(value / max) * 100}%`, 
                    width: barWidth,
                    backgroundColor: models[index % models.length].color,
                    opacity: models[index % models.length].id === selectedModel ? 1 : 0.6
                  }}
                ></div>
              </div>
              <span className="text-xs text-center truncate w-full">{labels[index]}</span>
            </div>
          ))}
        </div>
      </div>
    );
  };

  const CustomLineChart = ({ data, labels, max = 100, height = 250 }) => {
    const selectedModelData = data[selectedModel];
    const maxValue = Object.values(data).flat().reduce((a, b) => Math.max(a, b), 0);
    
    return (
      <div className="w-full relative" style={{ height: `${height}px` }}>
        {/* Background grid */}
        <div className="absolute inset-0 border-l border-t border-border grid grid-rows-4 grid-cols-4">
          {Array(16).fill(0).map((_, i) => (
            <div key={i} className="border-r border-b border-border/30"></div>
          ))}
        </div>
        
        {/* Y-axis labels */}
        <div className="absolute left-0 inset-y-0 w-10 flex flex-col justify-between text-xs text-muted-foreground">
          {[maxValue, Math.floor(maxValue * 0.66), Math.floor(maxValue * 0.33), 0].map((value, i) => (
            <div key={i} className="relative -ml-8">
              {value}
            </div>
          ))}
        </div>
        
        {/* X-axis labels */}
        <div className="absolute bottom-0 inset-x-0 h-6 flex justify-between text-xs text-muted-foreground">
          {labels.map((label, i) => (
            <div key={i} className="relative" style={{ left: `${(i / (labels.length - 1)) * 100}%` }}>
              {label}
            </div>
          ))}
        </div>
        
        {/* Lines */}
        <div className="absolute inset-x-0 top-0 bottom-6 px-10">
          {Object.entries(data).map(([modelId, values]) => {
            const points = values.map((value, i) => 
              `${(i / (values.length - 1)) * 100}% ${100 - (value / maxValue) * 100}%`
            ).join(', ');
            
            const modelInfo = models.find(m => m.id === modelId);
            if (!modelInfo) return null;
            
            return (
              <svg 
                key={modelId} 
                className="absolute inset-0 w-full h-full overflow-visible"
                preserveAspectRatio="none"
              >
                <polyline
                  points={points}
                  fill="none"
                  stroke={modelInfo.color}
                  strokeWidth={modelId === selectedModel ? 3 : 1.5}
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  vectorEffect="non-scaling-stroke"
                />
                
                {modelId === selectedModel && values.map((value, i) => (
                  <circle
                    key={i}
                    cx={`${(i / (values.length - 1)) * 100}%`}
                    cy={`${100 - (value / maxValue) * 100}%`}
                    r="4"
                    fill={modelInfo.color}
                    strokeWidth="2"
                    stroke="white"
                  />
                ))}
              </svg>
            );
          })}
        </div>
      </div>
    );
  };

  return (
    <div className="w-full max-w-6xl mx-auto bg-card rounded-xl shadow-lg overflow-hidden">
      <div className="p-6 border-b border-border">
        <h1 className="text-3xl font-bold text-card-foreground">AI Model Comparison Dashboard</h1>
        <p className="text-muted-foreground mt-2">Interactive analytics for leading language models</p>
      </div>

      <div className="flex flex-col md:flex-row">
        {/* Sidebar */}
        <div className="md:w-64 bg-accent p-4 flex flex-col gap-2">
          {models.map(model => (
            <button
              key={model.id}
              className={cn(
                "p-3 rounded-lg text-left transition-all flex items-center gap-2",
                selectedModel === model.id 
                  ? "bg-primary text-primary-foreground" 
                  : "hover:bg-primary/10 text-foreground"
              )}
              onClick={() => setSelectedModel(model.id)}
            >
              <div 
                className="w-3 h-3 rounded-full" 
                style={{ backgroundColor: model.color }} 
              />
              <span>{model.name}</span>
            </button>
          ))}
          
          <div className="mt-8 pt-4 border-t border-border">
            <h3 className="font-semibold mb-2">View Data</h3>
            <div className="flex flex-col gap-1">
              {[
                { id: "performance", label: "Performance", icon: <Activity size={16} /> },
                { id: "features", label: "Features", icon: <CheckCircle size={16} /> }
              ].map(tab => (
                <button
                  key={tab.id}
                  className={cn(
                    "p-2 rounded-lg text-left transition-all flex items-center gap-2 text-sm",
                    activeTab === tab.id 
                      ? "bg-accent-foreground/10 text-accent-foreground" 
                      : "hover:bg-accent-foreground/5 text-accent-foreground/80"
                  )}
                  onClick={() => setActiveTab(tab.id)}
                >
                  {tab.icon}
                  <span>{tab.label}</span>
                </button>
              ))}
            </div>
          </div>
        </div>

        {/* Main content */}
        <div className="flex-1 p-6">
          {activeTab === "performance" && (
            <div>
              <div className="flex items-center justify-between mb-6">
                <h2 className="text-xl font-semibold">Performance Metrics</h2>
                <div className="flex gap-2">
                  <button className="px-3 py-1 text-sm bg-secondary rounded-md">Quarterly</button>
                  <button className="px-3 py-1 text-sm hover:bg-secondary rounded-md">Monthly</button>
                </div>
              </div>
              
              <div className="mb-8 mt-6">
                <h3 className="text-lg font-medium mb-4">Quarterly Performance Trend</h3>
                <CustomLineChart 
                  data={performanceData} 
                  labels={quarters}
                  max={100}
                  height={240}
                />
              </div>

              <div className="mt-12">
                <h3 className="text-lg font-medium mb-4">Task Category Performance</h3>
                <div className="flex gap-2 mb-4">
                  {models.map(model => (
                    <div key={model.id} className="flex items-center gap-1">
                      <div 
                        className="w-3 h-3 rounded-full" 
                        style={{ 
                          backgroundColor: model.color,
                          opacity: model.id === selectedModel ? 1 : 0.6
                        }} 
                      />
                      <span className="text-xs text-muted-foreground">{model.name}</span>
                    </div>
                  ))}
                </div>
                <CustomBarChart 
                  data={[
                    accuracyData["gpt-4"][0],
                    accuracyData["claude-3"][0],
                    accuracyData["llama-3"][0],
                    accuracyData["mistral"][0],
                  ]} 
                  labels={models.map(m => m.name)}
                  max={100}
                  height={200}
                />
                <div className="flex justify-between items-center mt-2">
                  <div className="text-sm font-medium">Category: <span className="text-accent-foreground">Translation</span></div>
                  <div className="flex gap-1">
                    {accuracyData.categories.map((cat, i) => (
                      <button 
                        key={i}
                        className={cn(
                          "px-2 py-1 text-xs rounded",
                          i === 0 ? "bg-primary text-primary-foreground" : "hover:bg-secondary"
                        )}
                      >
                        {cat}
                      </button>
                    ))}
                  </div>
                </div>
              </div>
            </div>
          )}

          {activeTab === "features" && (
            <div>
              <h2 className="text-xl font-semibold mb-6">Model Features</h2>
              
              <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
                <div className="bg-card border border-border rounded-lg p-4">
                  <h3 className="text-lg font-medium flex items-center gap-2 mb-3">
                    <CheckCircle size={20} className="text-emerald-500" />
                    Strengths
                  </h3>
                  <ul className="space-y-2">
                    {modelDetails[selectedModel as keyof typeof modelDetails].strengths.map((strength, i) => (
                      <li key={i} className="flex items-center gap-2">
                        <div className="w-1.5 h-1.5 rounded-full bg-emerald-500" />
                        <span>{strength}</span>
                      </li>
                    ))}
                  </ul>
                </div>
                
                <div className="bg-card border border-border rounded-lg p-4">
                  <h3 className="text-lg font-medium flex items-center gap-2 mb-3">
                    <AlertCircle size={20} className="text-amber-500" />
                    Limitations
                  </h3>
                  <ul className="space-y-2">
                    {modelDetails[selectedModel as keyof typeof modelDetails].limitations.map((limitation, i) => (
                      <li key={i} className="flex items-center gap-2">
                        <div className="w-1.5 h-1.5 rounded-full bg-amber-500" />
                        <span>{limitation}</span>
                      </li>
                    ))}
                  </ul>
                </div>
              </div>
              
              <div className="mt-6 grid grid-cols-1 md:grid-cols-2 gap-6">
                <div className="bg-card border border-border rounded-lg p-4">
                  <h3 className="text-lg font-medium flex items-center gap-2 mb-3">
                    <Zap size={20} className="text-blue-500" />
                    Processing Speed
                  </h3>
                  <div className="mt-4">
                    <div className="flex justify-between mb-1">
                      <span className="text-sm text-muted-foreground">Score</span>
                      <span className="font-medium">{modelDetails[selectedModel as keyof typeof modelDetails].speed}/100</span>
                    </div>
                    <div className="w-full bg-muted rounded-full h-2.5">
                      <div 
                        className="bg-blue-500 h-2.5 rounded-full" 
                        style={{ width: `${modelDetails[selectedModel as keyof typeof modelDetails].speed}%` }}
                      ></div>
                    </div>
                  </div>
                </div>
                
                <div className="bg-card border border-border rounded-lg p-4">
                  <h3 className="text-lg font-medium flex items-center gap-2 mb-3">
                    <Activity size={20} className="text-purple-500" />
                    Accuracy Rating
                  </h3>
                  <div className="mt-4">
                    <div className="flex justify-between mb-1">
                      <span className="text-sm text-muted-foreground">Score</span>
                      <span className="font-medium">{modelDetails[selectedModel as keyof typeof modelDetails].accuracy}/100</span>
                    </div>
                    <div className="w-full bg-muted rounded-full h-2.5">
                      <div 
                        className="bg-purple-500 h-2.5 rounded-full" 
                     style={{ width: `${modelDetails[selectedModel as keyof typeof modelDetails].accuracy}%` }}

                      ></div>
                    </div>
                  </div>
                </div>
              </div>
              
              <div className="mt-6 p-4 bg-card border border-border rounded-lg">
                <h3 className="text-lg font-medium flex items-center gap-2 mb-3">
                  <BarChart3 size={20} className="text-teal-500" />
                  Model Comparison
                </h3>
                
                <div className="grid grid-cols-2 gap-4 mt-4">
                  {models.map(model => (
                    <div 
                      key={model.id} 
                      className={cn(
                        "p-3 rounded-lg border transition-all",
                        model.id === selectedModel 
                          ? "border-primary bg-primary/5" 
                          : "border-border hover:bg-secondary/20"
                      )}
                      onClick={() => setSelectedModel(model.id)}
                    >
                      <div className="flex items-center gap-2">
                        <div 
                          className="w-3 h-3 rounded-full" 
                          style={{ backgroundColor: model.color }} 
                        />
                        <span className="font-medium">{model.name}</span>
                      </div>
                      <div className="flex justify-between mt-2 text-sm">
                        <span className="text-muted-foreground">Speed:</span>
                        <span>{modelDetails[model.id as keyof typeof modelDetails].speed}/100</span>
                      </div>
                      <div className="flex justify-between mt-1 text-sm">
                        <span className="text-muted-foreground">Accuracy:</span>
                        <span>{modelDetails[model.id as keyof typeof modelDetails].accuracy}/100</span>
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

Dependencies

More by LAKSHAY SINGLA

View all
  • Futuristic File Uploader

    Futuristic File Uploader

    33

More in AI chats

View all
  • AI Actions

    AI Actions

    317
  • Color Picker

    Color Picker

    73
  • Agent Chat

    Agent Chat

    17
  • Prompt with Model Picker

    Prompt with Model Picker

    2
  • Approval Card

    Approval Card

    12
  • System Message

    System Message

    53
  • Message

    Message

    48
  • AI Task List

    AI Task List

    158