From 30f6ef0d95e0ee009732f823c9806799720dbcb3 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 23 Apr 2026 11:21:53 +0000 Subject: [PATCH] feat(ui): another small batch to shadcn - Navbar/CommunityEngagementButtons: antd Button + @ant-design icons \u2192 shadcn Button asChild + lucide Slack/Github. Indigo shadow preserved. - playground/{Chat,Responses}ImageUpload: antd Upload.Dragger + antd Tooltip + @ant-design PaperClipOutlined \u2192 hidden + shadcn Tooltip + lucide Paperclip. Keeps beforeUpload contract. - playground/FilePreviewCard: @ant-design DeleteOutlined/FilePdfOutlined \u2192 lucide Trash2/FileText; semantic tokens throughout. - router_settings/TagFilteringToggle + RoutingStrategySelector: antd Switch/Select \u2192 shadcn Switch/Select. onChange \u2192 onValueChange / onCheckedChange. Strategy option now renders a two-line label via flex-col inside the SelectItem. Gates: TS \u2713 | Build \u2713. Co-authored-by: yuneng-jiang --- .../CommunityEngagementButtons.tsx | 35 +++++++---- .../playground/chat_ui/ChatImageUpload.tsx | 62 ++++++++++++------- .../playground/chat_ui/FilePreviewCard.tsx | 23 ++++--- .../chat_ui/ResponsesImageUpload.tsx | 57 ++++++++++------- .../RoutingStrategySelector.tsx | 52 ++++++++++------ .../router_settings/TagFilteringToggle.tsx | 18 +++--- 6 files changed, 153 insertions(+), 94 deletions(-) diff --git a/ui/litellm-dashboard/src/components/Navbar/CommunityEngagementButtons/CommunityEngagementButtons.tsx b/ui/litellm-dashboard/src/components/Navbar/CommunityEngagementButtons/CommunityEngagementButtons.tsx index 649bcc0b589..df9fea7e6c6 100644 --- a/ui/litellm-dashboard/src/components/Navbar/CommunityEngagementButtons/CommunityEngagementButtons.tsx +++ b/ui/litellm-dashboard/src/components/Navbar/CommunityEngagementButtons/CommunityEngagementButtons.tsx @@ -1,12 +1,11 @@ import { useDisableShowPrompts } from "@/app/(dashboard)/hooks/useDisableShowPrompts"; -import { GithubOutlined, SlackOutlined } from "@ant-design/icons"; -import { Button } from "antd"; +import { Button } from "@/components/ui/button"; +import { Github, Slack } from "lucide-react"; import React from "react"; export const CommunityEngagementButtons: React.FC = () => { const disableShowPrompts = useDisableShowPrompts(); - // Hide buttons if prompts are disabled if (disableShowPrompts) { return null; } @@ -14,22 +13,32 @@ export const CommunityEngagementButtons: React.FC = () => { return ( <> ); diff --git a/ui/litellm-dashboard/src/components/playground/chat_ui/ChatImageUpload.tsx b/ui/litellm-dashboard/src/components/playground/chat_ui/ChatImageUpload.tsx index 55527d997ac..a67c600ec0b 100644 --- a/ui/litellm-dashboard/src/components/playground/chat_ui/ChatImageUpload.tsx +++ b/ui/litellm-dashboard/src/components/playground/chat_ui/ChatImageUpload.tsx @@ -1,43 +1,61 @@ -import React from "react"; -import { Upload, Tooltip } from "antd"; -import { PaperClipOutlined } from "@ant-design/icons"; - -const { Dragger } = Upload; +import React, { useRef } from "react"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { Paperclip } from "lucide-react"; interface ChatImageUploadProps { chatUploadedImage: File | null; + // eslint-disable-next-line @typescript-eslint/no-unused-vars chatImagePreviewUrl: string | null; onImageUpload: (file: File) => false; + // eslint-disable-next-line @typescript-eslint/no-unused-vars onRemoveImage: () => void; } +/** + * Thin hidden-file-input wrapper around the old Ant Design Dragger. The + * previous implementation used antd Upload's `beforeUpload` hook which + * returns `false` to intercept the file \u2014 we preserve that contract. + */ const ChatImageUpload: React.FC = ({ chatUploadedImage, - chatImagePreviewUrl, onImageUpload, - onRemoveImage, }) => { + const inputRef = useRef(null); + + if (chatUploadedImage) return null; + return ( <> - {/* Subtle upload button - only show when no image */} - {!chatUploadedImage && ( - - + { + const file = e.target.files?.[0]; + if (file) onImageUpload(file); + e.target.value = ""; + }} + /> + + + - - - )} + + Attach image or PDF + + ); }; diff --git a/ui/litellm-dashboard/src/components/playground/chat_ui/FilePreviewCard.tsx b/ui/litellm-dashboard/src/components/playground/chat_ui/FilePreviewCard.tsx index 26bdf07eda9..5e7e069a9a0 100644 --- a/ui/litellm-dashboard/src/components/playground/chat_ui/FilePreviewCard.tsx +++ b/ui/litellm-dashboard/src/components/playground/chat_ui/FilePreviewCard.tsx @@ -1,4 +1,4 @@ -import { DeleteOutlined, FilePdfOutlined } from "@ant-design/icons"; +import { FileText, Trash2 } from "lucide-react"; interface FilePreviewCardProps { file: File; @@ -11,31 +11,36 @@ function FilePreviewCard({ file, previewUrl, onRemove }: FilePreviewCardProps) { return (
-
+
{isPdf ? ( -
- +
+
) : ( + // eslint-disable-next-line @next/next/no-img-element Upload preview )}
-
{file.name}
-
+
+ {file.name} +
+
{isPdf ? "PDF" : "Image"}
diff --git a/ui/litellm-dashboard/src/components/playground/chat_ui/ResponsesImageUpload.tsx b/ui/litellm-dashboard/src/components/playground/chat_ui/ResponsesImageUpload.tsx index d5abf13a7d3..6b05fd0bd70 100644 --- a/ui/litellm-dashboard/src/components/playground/chat_ui/ResponsesImageUpload.tsx +++ b/ui/litellm-dashboard/src/components/playground/chat_ui/ResponsesImageUpload.tsx @@ -1,43 +1,56 @@ -import React from "react"; -import { Upload, Tooltip } from "antd"; -import { PaperClipOutlined } from "@ant-design/icons"; - -const { Dragger } = Upload; +import React, { useRef } from "react"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { Paperclip } from "lucide-react"; interface ResponsesImageUploadProps { responsesUploadedImage: File | null; + // eslint-disable-next-line @typescript-eslint/no-unused-vars responsesImagePreviewUrl: string | null; onImageUpload: (file: File) => false; + // eslint-disable-next-line @typescript-eslint/no-unused-vars onRemoveImage: () => void; } const ResponsesImageUpload: React.FC = ({ responsesUploadedImage, - responsesImagePreviewUrl, onImageUpload, - onRemoveImage, }) => { + const inputRef = useRef(null); + + if (responsesUploadedImage) return null; + return ( <> - {/* Subtle upload button - only show when no image */} - {!responsesUploadedImage && ( - - + { + const file = e.target.files?.[0]; + if (file) onImageUpload(file); + e.target.value = ""; + }} + /> + + + - - - )} + + Attach image or PDF + + ); }; diff --git a/ui/litellm-dashboard/src/components/router_settings/RoutingStrategySelector.tsx b/ui/litellm-dashboard/src/components/router_settings/RoutingStrategySelector.tsx index c64fb410e7c..db9769d100d 100644 --- a/ui/litellm-dashboard/src/components/router_settings/RoutingStrategySelector.tsx +++ b/ui/litellm-dashboard/src/components/router_settings/RoutingStrategySelector.tsx @@ -1,10 +1,17 @@ import React from "react"; -import { Select } from "antd"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; interface RoutingStrategySelectorProps { selectedStrategy: string | null; availableStrategies: string[]; routingStrategyDescriptions: { [key: string]: string }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any routerFieldsMetadata: { [key: string]: any }; onStrategyChange: (strategy: string) => void; } @@ -19,32 +26,38 @@ const RoutingStrategySelector: React.FC = ({ return (
-
@@ -52,4 +65,3 @@ const RoutingStrategySelector: React.FC = ({ }; export default RoutingStrategySelector; - diff --git a/ui/litellm-dashboard/src/components/router_settings/TagFilteringToggle.tsx b/ui/litellm-dashboard/src/components/router_settings/TagFilteringToggle.tsx index 725c75a3f67..d26badd8eae 100644 --- a/ui/litellm-dashboard/src/components/router_settings/TagFilteringToggle.tsx +++ b/ui/litellm-dashboard/src/components/router_settings/TagFilteringToggle.tsx @@ -1,8 +1,9 @@ import React from "react"; -import { Switch } from "antd"; +import { Switch } from "@/components/ui/switch"; interface TagFilteringToggleProps { enabled: boolean; + // eslint-disable-next-line @typescript-eslint/no-explicit-any routerFieldsMetadata: { [key: string]: any }; onToggle: (enabled: boolean) => void; } @@ -16,11 +17,13 @@ const TagFilteringToggle: React.FC = ({
-
@@ -47,4 +50,3 @@ const TagFilteringToggle: React.FC = ({ }; export default TagFilteringToggle; -