Farigh UI Logo

Farigh UI

Installation

npm install recharts

Source Code

token-leaderboard-chart.tsx
1"use client";
2
3import React, { useState } from "react";
4import {
5  Bar,
6  BarChart,
7  CartesianGrid,
8  ResponsiveContainer,
9  Tooltip,
10  XAxis,
11  YAxis,
12} from "recharts";
13
14interface ModelData {
15  name: string;
16  value: number;
17  color: string;
18}
19
20interface ChartDataPoint {
21  date: string;
22  Others: number;
23  "Grok Code Fast 1": number;
24  "Claude Sonnet 4": number;
25  "Gemini 2.5 Flash": number;
26  "Sonoma Sky Alpha": number;
27  "Gemini 2.0 Flash": number;
28  "DeepSeek V3.1 (free)": number;
29  "Grok 4 Fast (free)": number;
30  "GPT-4.1 Mini": number;
31  "DeepSeek V3 0324": number;
32  [key: string]: string | number;
33}
34
35const chartData: ChartDataPoint[] = [
36  {
37    date: "21 Oct 2024",
38    Others: 50,
39    "Grok Code Fast 1": 30,
40    "Claude Sonnet 4": 15,
41    "Gemini 2.5 Flash": 10,
42    "Sonoma Sky Alpha": 8,
43    "Gemini 2.0 Flash": 6,
44    "DeepSeek V3.1 (free)": 5,
45    "Grok 4 Fast (free)": 4,
46    "GPT-4.1 Mini": 4,
47    "DeepSeek V3 0324": 3,
48  },
49  {
50    date: "25 Nov",
51    Others: 80,
52    "Grok Code Fast 1": 45,
53    "Claude Sonnet 4": 25,
54    "Gemini 2.5 Flash": 18,
55    "Sonoma Sky Alpha": 12,
56    "Gemini 2.0 Flash": 10,
57    "DeepSeek V3.1 (free)": 8,
58    "Grok 4 Fast (free)": 7,
59    "GPT-4.1 Mini": 6,
60    "DeepSeek V3 0324": 5,
61  },
62  {
63    date: "30 Dec",
64    Others: 120,
65    "Grok Code Fast 1": 70,
66    "Claude Sonnet 4": 38,
67    "Gemini 2.5 Flash": 28,
68    "Sonoma Sky Alpha": 20,
69    "Gemini 2.0 Flash": 16,
70    "DeepSeek V3.1 (free)": 14,
71    "Grok 4 Fast (free)": 12,
72    "GPT-4.1 Mini": 10,
73    "DeepSeek V3 0324": 8,
74  },
75  {
76    date: "3 Feb",
77    Others: 180,
78    "Grok Code Fast 1": 95,
79    "Claude Sonnet 4": 52,
80    "Gemini 2.5 Flash": 38,
81    "Sonoma Sky Alpha": 28,
82    "Gemini 2.0 Flash": 22,
83    "DeepSeek V3.1 (free)": 20,
84    "Grok 4 Fast (free)": 17,
85    "GPT-4.1 Mini": 15,
86    "DeepSeek V3 0324": 12,
87  },
88  {
89    date: "10 Mar",
90    Others: 280,
91    "Grok Code Fast 1": 160,
92    "Claude Sonnet 4": 85,
93    "Gemini 2.5 Flash": 58,
94    "Sonoma Sky Alpha": 42,
95    "Gemini 2.0 Flash": 34,
96    "DeepSeek V3.1 (free)": 30,
97    "Grok 4 Fast (free)": 26,
98    "GPT-4.1 Mini": 23,
99    "DeepSeek V3 0324": 19,
100  },
101  {
102    date: "14 Apr",
103    Others: 380,
104    "Grok Code Fast 1": 220,
105    "Claude Sonnet 4": 118,
106    "Gemini 2.5 Flash": 78,
107    "Sonoma Sky Alpha": 56,
108    "Gemini 2.0 Flash": 45,
109    "DeepSeek V3.1 (free)": 40,
110    "Grok 4 Fast (free)": 35,
111    "GPT-4.1 Mini": 31,
112    "DeepSeek V3 0324": 26,
113  },
114  {
115    date: "19 May",
116    Others: 520,
117    "Grok Code Fast 1": 310,
118    "Claude Sonnet 4": 165,
119    "Gemini 2.5 Flash": 108,
120    "Sonoma Sky Alpha": 78,
121    "Gemini 2.0 Flash": 62,
122    "DeepSeek V3.1 (free)": 56,
123    "Grok 4 Fast (free)": 48,
124    "GPT-4.1 Mini": 43,
125    "DeepSeek V3 0324": 36,
126  },
127  {
128    date: "23 Jun",
129    Others: 680,
130    "Grok Code Fast 1": 420,
131    "Claude Sonnet 4": 225,
132    "Gemini 2.5 Flash": 148,
133    "Sonoma Sky Alpha": 106,
134    "Gemini 2.0 Flash": 84,
135    "DeepSeek V3.1 (free)": 76,
136    "Grok 4 Fast (free)": 65,
137    "GPT-4.1 Mini": 58,
138    "DeepSeek V3 0324": 49,
139  },
140  {
141    date: "28 Jul",
142    Others: 850,
143    "Grok Code Fast 1": 540,
144    "Claude Sonnet 4": 290,
145    "Gemini 2.5 Flash": 190,
146    "Sonoma Sky Alpha": 136,
147    "Gemini 2.0 Flash": 108,
148    "DeepSeek V3.1 (free)": 98,
149    "Grok 4 Fast (free)": 84,
150    "GPT-4.1 Mini": 75,
151    "DeepSeek V3 0324": 63,
152  },
153  {
154    date: "1 Sept",
155    Others: 1050,
156    "Grok Code Fast 1": 680,
157    "Claude Sonnet 4": 365,
158    "Gemini 2.5 Flash": 240,
159    "Sonoma Sky Alpha": 172,
160    "Gemini 2.0 Flash": 136,
161    "DeepSeek V3.1 (free)": 124,
162    "Grok 4 Fast (free)": 106,
163    "GPT-4.1 Mini": 94,
164    "DeepSeek V3 0324": 79,
165  },
166  {
167    date: "15 September 2025",
168    Others: 1810,
169    "Grok Code Fast 1": 1150,
170    "Claude Sonnet 4": 586,
171    "Gemini 2.5 Flash": 325,
172    "Sonoma Sky Alpha": 227,
173    "Gemini 2.0 Flash": 187,
174    "DeepSeek V3.1 (free)": 180,
175    "Grok 4 Fast (free)": 158,
176    "GPT-4.1 Mini": 157,
177    "DeepSeek V3 0324": 142,
178  },
179  {
180    date: "6 Oct",
181    Others: 1650,
182    "Grok Code Fast 1": 1050,
183    "Claude Sonnet 4": 535,
184    "Gemini 2.5 Flash": 296,
185    "Sonoma Sky Alpha": 207,
186    "Gemini 2.0 Flash": 170,
187    "DeepSeek V3.1 (free)": 164,
188    "Grok 4 Fast (free)": 144,
189    "GPT-4.1 Mini": 143,
190    "DeepSeek V3 0324": 129,
191  },
192];
193
194const models = [
195  { key: "DeepSeek V3 0324", color: "#FFA07A" },
196  { key: "GPT-4.1 Mini", color: "#FFB6C1" },
197  { key: "Grok 4 Fast (free)", color: "#DDA0DD" },
198  { key: "DeepSeek V3.1 (free)", color: "#87CEEB" },
199  { key: "Gemini 2.0 Flash", color: "#98FB98" },
200  { key: "Sonoma Sky Alpha", color: "#F0E68C" },
201  { key: "Gemini 2.5 Flash", color: "#FFDAB9" },
202  { key: "Claude Sonnet 4", color: "#DEB887" },
203  { key: "Grok Code Fast 1", color: "#CD853F" },
204  { key: "Others", color: "#FF69B4" },
205];
206
207const formatValue = (value: number): string => {
208  if (value >= 1000) {
209    return `${(value / 1000).toFixed(2)}T`;
210  }
211  return `${value}B`;
212};
213
214interface TooltipProps {
215  active?: boolean;
216  payload?: Array<{
217    payload: ChartDataPoint;
218  }>;
219}
220
221const CustomTooltip = ({ active, payload }: TooltipProps) => {
222  if (active && payload && payload.length) {
223    const data = payload[0].payload;
224    const total = models.reduce(
225      (sum, model) => {
226        const value = data[model.key];
227        return sum + (typeof value === 'number' ? value : 0);
228      },
229      0
230    );
231
232    const modelData: ModelData[] = models.map((model) => {
233      const value = data[model.key];
234      return {
235        name: model.key,
236        value: typeof value === 'number' ? value : 0,
237        color: model.color,
238      };
239    });
240
241    return (
242      <div className="bg-primary/90 rounded-lg p-4 shadow-xl min-w-[240px]">
243        <div className="text-xs text-gray-400 mb-3 pb-2">
244          {data.date}
245        </div>
246        <div className="space-y-2">
247          {modelData.map((model, idx) => (
248            <div key={idx} className="flex items-center justify-between gap-4">
249              <div className="flex items-center gap-2 min-w-0">
250                <div
251                  className="w-2 h-2 rounded-sm flex-shrink-0"
252                  style={{ backgroundColor: model.color }}
253                />
254                <span className="text-xs text-gray-300 truncate">
255                  {model.name}
256                </span>
257              </div>
258              <span className="text-xs font-medium text-white flex-shrink-0">
259                {formatValue(model.value)}
260              </span>
261            </div>
262          ))}
263          <div className="pt-2 mt-2 border-t border-gray-800">
264            <div className="flex items-center justify-between">
265              <span className="text-xs font-medium text-white">Total</span>
266              <span className="text-xs font-bold text-white">
267                {formatValue(total)}
268              </span>
269            </div>
270          </div>
271        </div>
272      </div>
273    );
274  }
275
276  return null;
277};
278
279export default function TokenLeaderboardChart() {
280  const [timeFilter] = useState("Top this week");
281
282  return (
283    <div className="flex items-center justify-center min-h-screen bg-primary p-8">
284      <div className="w-full max-w-6xl bg-[#0F0F0F] rounded-2xl p-8">
285        {/* Header */}
286        <div className="flex items-center justify-between mb-2">
287          <div className="flex items-center gap-3">
288            <svg
289              className="w-5 h-5 text-gray-400"
290              fill="none"
291              stroke="currentColor"
292              viewBox="0 0 24 24"
293            >
294              <path
295                strokeLinecap="round"
296                strokeLinejoin="round"
297                strokeWidth={2}
298                d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
299              />
300            </svg>
301            <h2 className="text-xl font-semibold text-white">Leaderboard</h2>
302          </div>
303          <button className="flex items-center gap-2 px-4 py-2 text-sm text-gray-300 hover:text-white bg-[#1A1A1A] hover:bg-[#252525] border border-gray-800 rounded-lg transition-colors">
304            {timeFilter}
305            <svg
306              className="w-4 h-4"
307              fill="none"
308              stroke="currentColor"
309              viewBox="0 0 24 24"
310            >
311              <path
312                strokeLinecap="round"
313                strokeLinejoin="round"
314                strokeWidth={2}
315                d="M19 9l-7 7-7-7"
316              />
317            </svg>
318          </button>
319        </div>
320
321        {/* Subtitle */}
322        <div className="flex items-center gap-2 mb-6">
323          <p className="text-sm text-primary-foreground">
324            Token usage across models on OpenRouter
325          </p>
326          <button className="text-primary-foreground hover:text-gray-400">
327            <svg
328              className="w-4 h-4"
329              fill="none"
330              stroke="currentColor"
331              viewBox="0 0 24 24"
332            >
333              <path
334                strokeLinecap="round"
335                strokeLinejoin="round"
336                strokeWidth={2}
337                d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
338              />
339            </svg>
340          </button>
341        </div>
342
343        {/* Chart */}
344        <div className="h-[450px] w-full">
345          <ResponsiveContainer width="100%" height="100%">
346            <BarChart data={chartData} barGap={2}>
347              <CartesianGrid
348                strokeDasharray="3 3"
349                stroke="#1F1F1F"
350                vertical={false}
351              />
352              <XAxis
353                dataKey="date"
354                stroke="#666"
355                tick={{ fontSize: 11, fill: "#999" }}
356                tickLine={false}
357                axisLine={{ stroke: "#1F1F1F" }}
358              />
359              <YAxis
360                stroke="#666"
361                tick={{ fontSize: 11, fill: "#999" }}
362                tickLine={false}
363                axisLine={{ stroke: "#1F1F1F" }}
364                tickFormatter={(value) => `${value / 1000}T`}
365              />
366              <Tooltip content={<CustomTooltip />} cursor={false} />
367              {models.map((model) => (
368                <Bar
369                  key={model.key}
370                  dataKey={model.key}
371                  stackId="a"
372                  fill={model.color}
373                  radius={0}
374                />
375              ))}
376            </BarChart>
377          </ResponsiveContainer>
378        </div>
379      </div>
380    </div>
381  );
382}
383

Related

Flight Card - San Francisco - Free React component preview

Flight Card - San Francisco

Flight Card - New York - Free React component preview

Flight Card - New York

Simplified Pricing - Free React component preview

Simplified Pricing

Mental Pricing - Free React component preview

Mental Pricing