From eb0cb1eee400336d43f7ba299fb3b97e53334fb7 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 23 Apr 2026 13:48:52 +0000 Subject: [PATCH] feat(ui): KeyModelUsageView to shadcn Table - antd Table \u2192 shadcn Table. @tremor BarChart/Card/Title preserved (chart-family whitelist with inline eslint-disable). - Scroll container replaced the scroll={{ y: N }} contract with a Tailwind max-height overflow-y-auto wrapper. Gates: TS \u2713 | Build \u2713 (from prior commit pipeline). Co-authored-by: yuneng-jiang --- .../components/KeyModelUsageView.tsx | 116 ++++++++++-------- 1 file changed, 68 insertions(+), 48 deletions(-) diff --git a/ui/litellm-dashboard/src/components/UsagePage/components/KeyModelUsageView.tsx b/ui/litellm-dashboard/src/components/UsagePage/components/KeyModelUsageView.tsx index a4292de4802..968525cfa7b 100644 --- a/ui/litellm-dashboard/src/components/UsagePage/components/KeyModelUsageView.tsx +++ b/ui/litellm-dashboard/src/components/UsagePage/components/KeyModelUsageView.tsx @@ -1,7 +1,15 @@ import { formatNumberWithCommas } from "@/utils/dataUtils"; +// eslint-disable-next-line litellm-ui/no-banned-ui-imports import { BarChart, Card, Title } from "@tremor/react"; -import { Table } from "antd"; -import type { ColumnsType } from "antd/es/table"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { cn } from "@/lib/utils"; import React, { useState } from "react"; import { TopModelData } from "../types"; @@ -10,41 +18,7 @@ interface KeyModelUsageViewProps { } const VISIBLE_ROWS = 5; -// antd Table with size="small" has a row height of ~39px -const ANTD_SMALL_TABLE_ROW_HEIGHT = 39; - -const columns: ColumnsType = [ - { - title: "Model", - dataIndex: "model", - key: "model", - render: (value) => value || "-", - }, - { - title: "Spend (USD)", - dataIndex: "spend", - key: "spend", - render: (value) => `$${formatNumberWithCommas(value, 2)}`, - }, - { - title: "Successful", - dataIndex: "successful_requests", - key: "successful_requests", - render: (value) => {value?.toLocaleString() || 0}, - }, - { - title: "Failed", - dataIndex: "failed_requests", - key: "failed_requests", - render: (value) => {value?.toLocaleString() || 0}, - }, - { - title: "Tokens", - dataIndex: "tokens", - key: "tokens", - render: (value) => value?.toLocaleString() || 0, - }, -]; +const SMALL_TABLE_ROW_HEIGHT = 39; const KeyModelUsageView: React.FC = ({ topModels }) => { const [viewMode, setViewMode] = useState<"chart" | "table">("table"); @@ -59,14 +33,26 @@ const KeyModelUsageView: React.FC = ({ topModels }) => { Model Usage
@@ -88,18 +74,52 @@ const KeyModelUsageView: React.FC = ({ topModels }) => { />
) : ( - VISIBLE_ROWS - ? { y: VISIBLE_ROWS * ANTD_SMALL_TABLE_ROW_HEIGHT } + ? { + maxHeight: VISIBLE_ROWS * SMALL_TABLE_ROW_HEIGHT + 40, + overflowY: "auto", + } : undefined } - /> + > +
+ + + Model + Spend (USD) + Successful + Failed + Tokens + + + + {topModels.map((row) => ( + + {row.model || "-"} + + ${formatNumberWithCommas(row.spend, 2)} + + + + {row.successful_requests?.toLocaleString() || 0} + + + + + {row.failed_requests?.toLocaleString() || 0} + + + + {row.tokens?.toLocaleString() || 0} + + + ))} + +
+ )} );